[mutter] monitor-manager: Notify privacy screen changes on hotkey press



commit 8cf3485ab0acec04c541dd9ba984e88f7a192d59
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon Aug 2 18:22:46 2021 +0200

    monitor-manager: Notify privacy screen changes on hotkey press
    
    When privacy screen is changed and this happens on explicit user request
    (that is not a setting change) we should notify about this via an OSD.
    
    To perform this, we keep track of the reason that lead to a privacy
    screen change, and when we record it we try to notify the user about.
    
    When the hardware has not an explicit hotkey signal but we record a
    change we must still fallback to this case.
    
    Fixes: #2105
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1952>

 src/backends/meta-monitor-manager-private.h       | 13 +++++
 src/backends/meta-monitor-manager.c               | 64 ++++++++++++++++++++++-
 src/backends/meta-settings-private.h              |  3 ++
 src/backends/meta-settings.c                      | 12 +++++
 src/backends/native/meta-monitor-manager-native.c | 25 +++++++--
 src/core/display.c                                | 22 ++++++++
 6 files changed, 135 insertions(+), 4 deletions(-)
---
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index abf63ce51a..443ad14cd3 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -35,6 +35,7 @@
 #include "backends/meta-viewport-info.h"
 #include "core/util-private.h"
 #include "meta/display.h"
+#include "meta/meta-enum-types.h"
 #include "meta/meta-monitor-manager.h"
 
 #define META_MONITOR_MANAGER_MIN_SCREEN_WIDTH 640
@@ -62,6 +63,14 @@ typedef enum _MetaLogicalMonitorLayoutMode
   META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2
 } MetaLogicalMonitorLayoutMode;
 
+/* The source the privacy screen change has been triggered */
+typedef enum
+{
+  META_PRIVACY_SCREEN_CHANGE_STATE_NONE,
+  META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_HOTKEY,
+  META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_SETTING,
+} MetaPrivacyScreenChangeState;
+
 /*
  * MetaCrtcAssignment:
  *
@@ -149,6 +158,8 @@ struct _MetaMonitorManager
   GnomePnpIds *pnp_ids;
 
   MetaMonitorSwitchConfigType current_switch_config;
+
+  MetaPrivacyScreenChangeState privacy_screen_change_state;
 };
 
 /**
@@ -440,4 +451,6 @@ MetaViewportInfo * meta_monitor_manager_get_viewports (MetaMonitorManager *manag
 
 GList * meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager);
 
+void meta_monitor_manager_maybe_emit_privacy_screen_change (MetaMonitorManager *manager);
+
 #endif /* META_MONITOR_MANAGER_PRIVATE_H */
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 2dff6539e1..3b650c62c0 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -83,6 +83,7 @@ enum
   MONITORS_CHANGED_INTERNAL,
   POWER_SAVE_MODE_CHANGED,
   CONFIRM_DISPLAY_CHANGE,
+  MONITOR_PRIVACY_SCREEN_CHANGED,
   SIGNALS_LAST
 };
 
@@ -1092,7 +1093,11 @@ apply_privacy_screen_settings (MetaMonitorManager *manager)
       meta_settings_is_privacy_screen_enabled (settings))
     return;
 
-  ensure_monitors_settings (manager);
+  if (ensure_monitors_settings (manager))
+    {
+      manager->privacy_screen_change_state =
+        META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_SETTING;
+    }
 }
 
 static void
@@ -1354,6 +1359,14 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
                   NULL, NULL, NULL,
                  G_TYPE_NONE, 0);
 
+  signals[MONITOR_PRIVACY_SCREEN_CHANGED] =
+    g_signal_new ("monitor-privacy-screen-changed",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 2, META_TYPE_LOGICAL_MONITOR, G_TYPE_BOOLEAN);
+
   obj_props[PROP_BACKEND] =
     g_param_spec_object ("backend",
                          "backend",
@@ -1446,6 +1459,55 @@ combine_gpu_lists (MetaMonitorManager    *manager,
   return list;
 }
 
+static void
+emit_privacy_screen_change (MetaMonitorManager *manager)
+{
+  GList *l;
+
+  for (l = manager->monitors; l; l = l->next)
+    {
+      MetaMonitor *monitor = l->data;
+      MetaPrivacyScreenState privacy_screen_state;
+      gboolean enabled;
+
+      if (!meta_monitor_is_active (monitor))
+        continue;
+
+      privacy_screen_state = meta_monitor_get_privacy_screen_state (monitor);
+      if (privacy_screen_state == META_PRIVACY_SCREEN_UNAVAILABLE)
+        continue;
+
+      enabled = !!(privacy_screen_state & META_PRIVACY_SCREEN_ENABLED);
+
+      g_signal_emit (manager, signals[MONITOR_PRIVACY_SCREEN_CHANGED], 0,
+                     meta_monitor_get_logical_monitor (monitor), enabled);
+    }
+}
+
+void
+meta_monitor_manager_maybe_emit_privacy_screen_change (MetaMonitorManager *manager)
+{
+  MetaPrivacyScreenChangeState reason = manager->privacy_screen_change_state;
+
+  if (reason == META_PRIVACY_SCREEN_CHANGE_STATE_NONE)
+    return;
+
+  if (reason == META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_HOTKEY)
+    emit_privacy_screen_change (manager);
+
+  if (reason != META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_SETTING)
+    {
+      MetaSettings *settings = meta_backend_get_settings (manager->backend);
+
+      meta_settings_set_privacy_screen_enabled (settings,
+        get_global_privacy_screen_state (manager) ==
+        META_PRIVACY_SCREEN_ENABLED);
+    }
+
+  meta_dbus_display_config_emit_monitors_changed (manager->display_config);
+  manager->privacy_screen_change_state = META_PRIVACY_SCREEN_CHANGE_STATE_NONE;
+}
+
 static gboolean
 meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
                                            GDBusMethodInvocation *invocation,
diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h
index a56a8bcc4a..fb9aea0dcb 100644
--- a/src/backends/meta-settings-private.h
+++ b/src/backends/meta-settings-private.h
@@ -80,4 +80,7 @@ int meta_settings_get_xwayland_disable_extensions (MetaSettings *settings);
 
 gboolean meta_settings_is_privacy_screen_enabled (MetaSettings *settings);
 
+void meta_settings_set_privacy_screen_enabled (MetaSettings *settings,
+                                               gboolean      enabled);
+
 #endif /* META_SETTINGS_PRIVATE_H */
diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c
index d11e0b720b..f672026ea5 100644
--- a/src/backends/meta-settings.c
+++ b/src/backends/meta-settings.c
@@ -478,6 +478,18 @@ meta_settings_is_privacy_screen_enabled (MetaSettings *settings)
   return settings->privacy_screen;
 }
 
+void
+meta_settings_set_privacy_screen_enabled (MetaSettings *settings,
+                                          gboolean      enabled)
+{
+  if (settings->privacy_screen == enabled)
+    return;
+
+  settings->privacy_screen = enabled;
+  g_settings_set_boolean (settings->privacy_settings, "privacy-screen",
+                          enabled);
+}
+
 MetaSettings *
 meta_settings_new (MetaBackend *backend)
 {
diff --git a/src/backends/native/meta-monitor-manager-native.c 
b/src/backends/native/meta-monitor-manager-native.c
index 4cd02468fe..7dcb9ae640 100644
--- a/src/backends/native/meta-monitor-manager-native.c
+++ b/src/backends/native/meta-monitor-manager-native.c
@@ -520,8 +520,23 @@ on_kms_resources_changed (MetaKms              *kms,
       return;
     }
 
-  if (changes == META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN)
-    return;
+  if (changes & META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN)
+    {
+      if (manager->privacy_screen_change_state ==
+          META_PRIVACY_SCREEN_CHANGE_STATE_NONE)
+        {
+          /* Privacy screen has been changed by "something", the best guess
+           * we can do is that has been triggered by an hotkey.
+           */
+          manager->privacy_screen_change_state =
+            META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_HOTKEY;
+        }
+
+      meta_monitor_manager_maybe_emit_privacy_screen_change (manager);
+
+      if (changes == META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN)
+        return;
+    }
 
   handle_hotplug_event (manager);
 }
@@ -710,7 +725,11 @@ on_kms_privacy_screen_update_result (const MetaKmsFeedback *kms_feedback,
   MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend));
 
   if (meta_kms_feedback_get_result (kms_feedback) == META_KMS_FEEDBACK_FAILED)
-    return;
+    {
+      manager->privacy_screen_change_state =
+        META_PRIVACY_SCREEN_CHANGE_STATE_NONE;
+      return;
+    }
 
   on_kms_resources_changed (kms,
                             META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN,
diff --git a/src/core/display.c b/src/core/display.c
index bb3918cf3a..288853368f 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -195,6 +195,12 @@ static void    prefs_changed_callback    (MetaPreference pref,
 static int mru_cmp (gconstpointer a,
                     gconstpointer b);
 
+static void
+meta_display_show_osd (MetaDisplay *display,
+                       gint         monitor_idx,
+                       const gchar *icon_name,
+                       const gchar *message);
+
 static void
 meta_display_get_property(GObject         *object,
                           guint            prop_id,
@@ -655,6 +661,19 @@ on_ui_scaling_factor_changed (MetaSettings *settings,
   meta_display_reload_cursor (display);
 }
 
+static void
+on_monitor_privacy_screen_changed (MetaDisplay        *display,
+                                   MetaLogicalMonitor *logical_monitor,
+                                   gboolean            enabled)
+{
+  meta_display_show_osd (display,
+                         logical_monitor->number,
+                         enabled ? "screen-privacy-symbolic"
+                                 : "screen-privacy-disabled-symbolic",
+                         enabled ? _("Privacy Screen Enabled")
+                                 : _("Privacy Screen Disabled"));
+}
+
 static gboolean
 meta_display_init_x11_display (MetaDisplay  *display,
                                GError      **error)
@@ -863,6 +882,9 @@ meta_display_new (MetaContext  *context,
   monitor_manager = meta_backend_get_monitor_manager (backend);
   g_signal_connect (monitor_manager, "monitors-changed-internal",
                     G_CALLBACK (on_monitors_changed_internal), display);
+  g_signal_connect_object (monitor_manager, "monitor-privacy-screen-changed",
+                           G_CALLBACK (on_monitor_privacy_screen_changed),
+                           display, G_CONNECT_SWAPPED);
 
   display->pad_action_mapper = meta_pad_action_mapper_new (monitor_manager);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]