mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 10:30:47 -05:00
321 lines
8.4 KiB
C
321 lines
8.4 KiB
C
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||
|
|
||
|
/*
|
||
|
* Copyright (C) 2017 Red Hat
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||
|
* 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
#include "config.h"
|
||
|
|
||
|
#include "backends/meta-settings-private.h"
|
||
|
|
||
|
#include <gio/gio.h>
|
||
|
|
||
|
#include "backends/meta-backend-private.h"
|
||
|
#include "backends/meta-logical-monitor.h"
|
||
|
#include "backends/meta-monitor-manager-private.h"
|
||
|
#include "ui/theme-private.h"
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
UI_SCALING_FACTOR_CHANGED,
|
||
|
EXPERIMENTAL_FEATURES_CHANGED,
|
||
|
|
||
|
N_SIGNALS
|
||
|
};
|
||
|
|
||
|
static guint signals[N_SIGNALS];
|
||
|
|
||
|
struct _MetaSettings
|
||
|
{
|
||
|
GObject parent;
|
||
|
|
||
|
MetaBackend *backend;
|
||
|
|
||
|
GSettings *mutter_settings;
|
||
|
|
||
|
int ui_scaling_factor;
|
||
|
|
||
|
MetaExperimentalFeature experimental_features;
|
||
|
gboolean experimental_features_overridden;
|
||
|
};
|
||
|
|
||
|
G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT)
|
||
|
|
||
|
static int
|
||
|
calculate_ui_scaling_factor (MetaSettings *settings)
|
||
|
{
|
||
|
MetaMonitorManager *monitor_manager =
|
||
|
meta_backend_get_monitor_manager (settings->backend);
|
||
|
GList *logical_monitors;
|
||
|
GList *l;
|
||
|
int max_scale = 1;
|
||
|
|
||
|
logical_monitors =
|
||
|
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||
|
for (l = logical_monitors; l; l = l->next)
|
||
|
{
|
||
|
MetaLogicalMonitor *logical_monitor = l->data;
|
||
|
|
||
|
max_scale = MAX (meta_logical_monitor_get_scale (logical_monitor),
|
||
|
max_scale);
|
||
|
}
|
||
|
|
||
|
return max_scale;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
get_xsettings_scaling_factor (void)
|
||
|
{
|
||
|
GdkScreen *screen;
|
||
|
GValue value = G_VALUE_INIT;
|
||
|
|
||
|
g_value_init (&value, G_TYPE_INT);
|
||
|
|
||
|
screen = gdk_screen_get_default ();
|
||
|
if (gdk_screen_get_setting (screen, "gdk-window-scaling-factor", &value))
|
||
|
return g_value_get_int (&value);
|
||
|
else
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
update_ui_scaling_factor (MetaSettings *settings)
|
||
|
{
|
||
|
int ui_scaling_factor;
|
||
|
|
||
|
if (meta_is_stage_views_scaled ())
|
||
|
{
|
||
|
ui_scaling_factor = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (meta_is_monitor_config_manager_enabled ())
|
||
|
ui_scaling_factor = calculate_ui_scaling_factor (settings);
|
||
|
else
|
||
|
ui_scaling_factor = get_xsettings_scaling_factor ();
|
||
|
}
|
||
|
|
||
|
if (settings->ui_scaling_factor != ui_scaling_factor)
|
||
|
{
|
||
|
settings->ui_scaling_factor = ui_scaling_factor;
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
xft_dpi_changed (GtkSettings *gtk_settings,
|
||
|
GParamSpec *pspec,
|
||
|
MetaSettings *settings)
|
||
|
{
|
||
|
/* This only matters when we rely on XSettings. */
|
||
|
if (meta_is_monitor_config_manager_enabled ())
|
||
|
return;
|
||
|
|
||
|
meta_settings_update_ui_scaling_factor (settings);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
x11_display_opened (MetaBackend *backend,
|
||
|
MetaSettings *settings)
|
||
|
{
|
||
|
/*
|
||
|
* gdk-window-scaling-factor is not exported to gtk-settings
|
||
|
* because it is handled inside gdk, so we use gtk-xft-dpi instead
|
||
|
* which also changes when the scale factor changes.
|
||
|
*
|
||
|
* TODO: Only rely on our own configured scale when we only have
|
||
|
* MetaMonitorConfigManager.
|
||
|
*/
|
||
|
g_signal_connect (gtk_settings_get_default (), "notify::gtk-xft-dpi",
|
||
|
G_CALLBACK (xft_dpi_changed), settings);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
meta_settings_update_ui_scaling_factor (MetaSettings *settings)
|
||
|
{
|
||
|
if (update_ui_scaling_factor (settings))
|
||
|
g_signal_emit (settings, signals[UI_SCALING_FACTOR_CHANGED], 0);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
meta_settings_get_ui_scaling_factor (MetaSettings *settings)
|
||
|
{
|
||
|
g_assert (settings->ui_scaling_factor != 0);
|
||
|
|
||
|
return settings->ui_scaling_factor;
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
meta_settings_is_experimental_feature_enabled (MetaSettings *settings,
|
||
|
MetaExperimentalFeature feature)
|
||
|
{
|
||
|
return !!(settings->experimental_features & feature);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
meta_settings_override_experimental_features (MetaSettings *settings)
|
||
|
{
|
||
|
settings->experimental_features = META_EXPERIMENTAL_FEATURE_NONE;
|
||
|
settings->experimental_features_overridden = TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
meta_settings_enable_experimental_feature (MetaSettings *settings,
|
||
|
MetaExperimentalFeature feature)
|
||
|
{
|
||
|
g_assert (settings->experimental_features_overridden);
|
||
|
|
||
|
settings->experimental_features |= feature;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
experimental_features_handler (GVariant *features_variant,
|
||
|
gpointer *result,
|
||
|
gpointer data)
|
||
|
{
|
||
|
MetaSettings *settings = data;
|
||
|
GVariantIter features_iter;
|
||
|
char *feature;
|
||
|
MetaExperimentalFeature features = META_EXPERIMENTAL_FEATURE_NONE;
|
||
|
|
||
|
if (settings->experimental_features_overridden)
|
||
|
{
|
||
|
*result = GINT_TO_POINTER (FALSE);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
g_variant_iter_init (&features_iter, features_variant);
|
||
|
while (g_variant_iter_loop (&features_iter, "s", &feature))
|
||
|
{
|
||
|
/* So far no experimental features defined. */
|
||
|
if (g_str_equal (feature, "scale-monitor-framebuffer"))
|
||
|
features |= META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER;
|
||
|
else if (g_str_equal (feature, "monitor-config-manager"))
|
||
|
features |= META_EXPERIMENTAL_FEATURE_MONITOR_CONFIG_MANAGER;
|
||
|
else
|
||
|
g_info ("Unknown experimental feature '%s'\n", feature);
|
||
|
}
|
||
|
|
||
|
if (features != settings->experimental_features)
|
||
|
{
|
||
|
settings->experimental_features = features;
|
||
|
*result = GINT_TO_POINTER (TRUE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*result = GINT_TO_POINTER (FALSE);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
update_experimental_features (MetaSettings *settings)
|
||
|
{
|
||
|
return GPOINTER_TO_INT (g_settings_get_mapped (settings->mutter_settings,
|
||
|
"experimental-features",
|
||
|
experimental_features_handler,
|
||
|
settings));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
mutter_settings_changed (GSettings *mutter_settings,
|
||
|
gchar *key,
|
||
|
MetaSettings *settings)
|
||
|
{
|
||
|
MetaExperimentalFeature old_experimental_features;
|
||
|
|
||
|
if (!g_str_equal (key, "experimental-features"))
|
||
|
return;
|
||
|
|
||
|
old_experimental_features = settings->experimental_features;
|
||
|
if (update_experimental_features (settings))
|
||
|
g_signal_emit (settings, signals[EXPERIMENTAL_FEATURES_CHANGED], 0,
|
||
|
(unsigned int) old_experimental_features);
|
||
|
}
|
||
|
|
||
|
MetaSettings *
|
||
|
meta_settings_new (MetaBackend *backend)
|
||
|
{
|
||
|
MetaSettings *settings;
|
||
|
|
||
|
settings = g_object_new (META_TYPE_SETTINGS, NULL);
|
||
|
settings->backend = backend;
|
||
|
|
||
|
g_signal_connect (backend, "x11-display-opened",
|
||
|
G_CALLBACK (x11_display_opened),
|
||
|
settings);
|
||
|
|
||
|
return settings;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
meta_settings_dispose (GObject *object)
|
||
|
{
|
||
|
MetaSettings *settings = META_SETTINGS (object);
|
||
|
|
||
|
g_clear_object (&settings->mutter_settings);
|
||
|
|
||
|
G_OBJECT_CLASS (meta_settings_parent_class)->dispose (object);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
meta_settings_init (MetaSettings *settings)
|
||
|
{
|
||
|
settings->mutter_settings = g_settings_new ("org.gnome.mutter");
|
||
|
g_signal_connect (settings->mutter_settings, "changed",
|
||
|
G_CALLBACK (mutter_settings_changed),
|
||
|
settings);
|
||
|
|
||
|
update_experimental_features (settings);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
meta_settings_post_init (MetaSettings *settings)
|
||
|
{
|
||
|
update_ui_scaling_factor (settings);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
meta_settings_class_init (MetaSettingsClass *klass)
|
||
|
{
|
||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
|
||
|
object_class->dispose = meta_settings_dispose;
|
||
|
|
||
|
signals[UI_SCALING_FACTOR_CHANGED] =
|
||
|
g_signal_new ("ui-scaling-factor-changed",
|
||
|
G_TYPE_FROM_CLASS (object_class),
|
||
|
G_SIGNAL_RUN_LAST,
|
||
|
0,
|
||
|
NULL, NULL, NULL,
|
||
|
G_TYPE_NONE, 0);
|
||
|
|
||
|
signals[EXPERIMENTAL_FEATURES_CHANGED] =
|
||
|
g_signal_new ("experimental-features-changed",
|
||
|
G_TYPE_FROM_CLASS (object_class),
|
||
|
G_SIGNAL_RUN_LAST,
|
||
|
0,
|
||
|
NULL, NULL, NULL,
|
||
|
G_TYPE_NONE, 1, G_TYPE_UINT);
|
||
|
}
|