[mutter/wip/carlosg/frozen-app-behavior: 1/2] core: Change behavior of "application is alive" checks




commit 46d6a9985ad2a961e1cd65fa5fb4c39826245538
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Sep 3 23:38:12 2021 +0200

    core: Change behavior of "application is alive" checks
    
    Change some things in these "app is alive" checks:
    - Pings are more pervasive, they are now non-configurable, have
      a shorter timeout (1s) to declare an application dead, and are
      produced more often during user interaction.
    - The dialog timeout is separated from this logic, it is still
      configurable, and has been fixed so dismissing reenables this
      timeout from the start, instead of the last failed ping (a new
      dialog popping up shortly after dismissing was likely a sore
      point with this feature that users failed to formulate).
    - As we want to tap into this logic further, MetaWindow now has
      a is-alive property, that other places in code can fetch and
      subscribe.
    
    This results in a separate logic between "the application does
    not respond" and "we are showing the close dialog" so that the
    former happens as timely as possible, while the latter might
    never happen.

 src/core/delete.c         | 10 +++++---
 src/core/display.c        |  6 ++---
 src/core/events.c         |  3 +++
 src/core/window-private.h |  9 +++++++
 src/core/window.c         | 65 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 86 insertions(+), 7 deletions(-)
---
diff --git a/src/core/delete.c b/src/core/delete.c
index 058764b088..d10bb59139 100644
--- a/src/core/delete.c
+++ b/src/core/delete.c
@@ -39,6 +39,8 @@ close_dialog_response_cb (MetaCloseDialog         *dialog,
 {
   if (response == META_CLOSE_DIALOG_RESPONSE_FORCE_CLOSE)
     meta_window_kill (window);
+  else
+    meta_window_ensure_close_dialog_timeout (window);
 }
 
 static void
@@ -57,14 +59,14 @@ meta_window_ensure_close_dialog (MetaWindow *window)
 }
 
 void
-meta_window_set_alive (MetaWindow *window,
-                       gboolean    is_alive)
+meta_window_set_show_close_dialog (MetaWindow *window,
+                                   gboolean    show)
 {
-  if (is_alive && window->close_dialog)
+  if (!show && window->close_dialog)
     {
       meta_close_dialog_hide (window->close_dialog);
     }
-  else if (!is_alive)
+  else if (show)
     {
       meta_window_ensure_close_dialog (window);
       meta_close_dialog_show (window->close_dialog);
diff --git a/src/core/display.c b/src/core/display.c
index 5d4a4da217..30d5a05ddc 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2186,9 +2186,9 @@ meta_display_ping_window (MetaWindow *window,
   ping_data->window = window;
   ping_data->serial = serial;
   ping_data->ping_timeout_id =
-    g_timeout_add (check_alive_timeout,
-                   meta_display_ping_timeout,
-                   ping_data);
+    g_timeout_add_seconds (1,
+                           meta_display_ping_timeout,
+                           ping_data);
   g_source_set_name_by_id (ping_data->ping_timeout_id, "[mutter] meta_display_ping_timeout");
 
   display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
diff --git a/src/core/events.c b/src/core/events.c
index 8afc720efd..81871a9e10 100644
--- a/src/core/events.c
+++ b/src/core/events.c
@@ -474,6 +474,9 @@ meta_display_handle_event (MetaDisplay        *display,
 #ifdef HAVE_WAYLAND
   if (compositor && !bypass_wayland)
     {
+      if (window && event->any.time != CLUTTER_CURRENT_TIME)
+        meta_window_check_alive (window, event->any.time);
+
       if (meta_wayland_compositor_handle_event (compositor, event))
         bypass_clutter = TRUE;
     }
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 18f62d1f45..2c6df48d4f 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -436,6 +436,9 @@ struct _MetaWindow
   /* whether focus should be restored on map */
   guint restore_focus_on_map : 1;
 
+  /* Whether the window is alive */
+  guint is_alive : 1;
+
   /* if non-NULL, the bounds of the window frame */
   cairo_region_t *frame_bounds;
 
@@ -563,6 +566,7 @@ struct _MetaWindow
   } placement;
 
   guint unmanage_idle_id;
+  guint close_dialog_timeout_id;
 
   pid_t client_pid;
 };
@@ -873,6 +877,11 @@ void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op);
 void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);
 
 void meta_window_set_alive (MetaWindow *window, gboolean is_alive);
+gboolean meta_window_get_alive (MetaWindow *window);
+
+void meta_window_set_show_close_dialog (MetaWindow *window,
+                                        gboolean show);
+void meta_window_ensure_close_dialog_timeout (MetaWindow *window);
 
 gboolean meta_window_has_pointer (MetaWindow *window);
 
diff --git a/src/core/window.c b/src/core/window.c
index b23f66e814..ffed90ea03 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -212,6 +212,7 @@ enum
   PROP_GTK_APP_MENU_OBJECT_PATH,
   PROP_GTK_MENUBAR_OBJECT_PATH,
   PROP_ON_ALL_WORKSPACES,
+  PROP_IS_ALIVE,
 
   PROP_LAST,
 };
@@ -628,6 +629,13 @@ meta_window_class_init (MetaWindowClass *klass)
                           FALSE,
                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
+  obj_props[PROP_IS_ALIVE] =
+    g_param_spec_boolean ("is-alive",
+                          "Is alive",
+                          "Whether the window responds to pings",
+                          FALSE,
+                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (object_class, PROP_LAST, obj_props);
 
   window_signals[WORKSPACE_CHANGED] =
@@ -724,6 +732,7 @@ meta_window_init (MetaWindow *self)
 {
   self->stamp = next_window_stamp++;
   meta_prefs_add_listener (prefs_changed_callback, self);
+  self->is_alive = TRUE;
 }
 
 static gboolean
@@ -8743,3 +8752,59 @@ meta_window_get_client_type (MetaWindow *window)
 {
   return window->client_type;
 }
+
+static gboolean
+meta_window_close_dialog_timeout (MetaWindow *window)
+{
+  meta_window_set_show_close_dialog (window, TRUE);
+  window->close_dialog_timeout_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+void
+meta_window_ensure_close_dialog_timeout (MetaWindow *window)
+{
+  guint check_alive_timeout = meta_prefs_get_check_alive_timeout ();
+
+  if (window->is_alive)
+    return;
+  if (window->close_dialog_timeout_id != 0)
+    return;
+  if (check_alive_timeout == 0)
+    return;
+
+  window->close_dialog_timeout_id =
+    g_timeout_add (check_alive_timeout,
+                   (GSourceFunc) meta_window_close_dialog_timeout,
+                   window);
+  g_source_set_name_by_id (window->close_dialog_timeout_id,
+                           "[mutter] meta_window_close_dialog_timeout");
+}
+
+void
+meta_window_set_alive (MetaWindow *window,
+                       gboolean    is_alive)
+{
+  if (window->is_alive == is_alive)
+    return;
+
+  window->is_alive = is_alive;
+  g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_IS_ALIVE]);
+
+  if (is_alive)
+    {
+      g_clear_handle_id (&window->close_dialog_timeout_id, g_source_remove);
+      meta_window_set_show_close_dialog (window, FALSE);
+    }
+  else
+    {
+      meta_window_ensure_close_dialog_timeout (window);
+    }
+}
+
+gboolean
+meta_window_get_alive (MetaWindow *window)
+{
+  return window->is_alive;
+}


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