emacs-diffs
[Top][All Lists]
Advanced

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

master 6f329bd239 1/2: "Fix" iconification handling on PGTK


From: Po Lu
Subject: master 6f329bd239 1/2: "Fix" iconification handling on PGTK
Date: Wed, 9 Nov 2022 08:05:44 -0500 (EST)

branch: master
commit 6f329bd239593c5f54e8f2b51b7974769d75db1f
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    "Fix" iconification handling on PGTK
    
    * src/pgtkterm.c (pgtk_iconify_frame): Write some more comments
    and refrain from setting the frame as iconified here.
    (map_event): Remove redundant braces.
    (window_state_event): Remove useless code and manage frame
    visibility as correctly as possible under Wayland while
    iconified.  (bug#55836)
---
 src/pgtkterm.c | 85 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 45 insertions(+), 40 deletions(-)

diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 491ba33882..3350676e3c 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -714,40 +714,42 @@ pgtk_set_window_size (struct frame *f, bool 
change_gravity,
 
 void
 pgtk_iconify_frame (struct frame *f)
-/* --------------------------------------------------------------------------
-     External: Iconify window
-   -------------------------------------------------------------------------- 
*/
 {
+  GtkWindow *window;
+
   /* Don't keep the highlight on an invisible frame.  */
+
   if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
-    FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
+    FRAME_DISPLAY_INFO (f)->highlight_frame = NULL;
+
+  /* If the frame is already iconified, return.  */
 
   if (FRAME_ICONIFIED_P (f))
     return;
 
-  block_input ();
+  /* Child frames on PGTK have no outer widgets.  In that case, simply
+     refuse to iconify the frame.  */
 
   if (FRAME_GTK_OUTER_WIDGET (f))
     {
       if (!FRAME_VISIBLE_P (f))
        gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
 
-      gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
-      SET_FRAME_VISIBLE (f, 0);
-      SET_FRAME_ICONIFIED (f, true);
-      unblock_input ();
-      return;
-    }
+      window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
 
-  /* Make sure the X server knows where the window should be positioned,
-     in case the user deiconifies with the window manager.  */
-  if (!FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
-    pgtk_set_offset (f, f->left_pos, f->top_pos, 0);
+      gtk_window_iconify (window);
 
-  SET_FRAME_ICONIFIED (f, true);
-  SET_FRAME_VISIBLE (f, 0);
+      /* Don't make the frame iconified here.  Doing so will cause it
+        to be skipped by redisplay, until GDK says it is deiconified
+        (see window_state_event for more details).  However, if the
+        window server rejects the iconification request, GDK will
+        never tell Emacs about the iconification not happening,
+        leading to the frame not being redisplayed until the next
+        window state change.  */
 
-  unblock_input ();
+      /* SET_FRAME_VISIBLE (f, 0);
+        SET_FRAME_ICONIFIED (f, true); */
+    }
 }
 
 static gboolean
@@ -5420,9 +5422,7 @@ map_event (GtkWidget *widget,
       /* Check if fullscreen was specified before we where mapped the
          first time, i.e. from the command line.  */
       if (!FRAME_X_OUTPUT (f)->has_been_visible)
-       {
-         set_fullscreen_state (f);
-       }
+       set_fullscreen_state (f);
 
       if (!iconified)
        {
@@ -5465,24 +5465,6 @@ window_state_event (GtkWidget *widget,
   inev.ie.kind = NO_EVENT;
   inev.ie.arg = Qnil;
 
-  if (f)
-    {
-      if (new_state & GDK_WINDOW_STATE_FOCUSED)
-       {
-         if (FRAME_ICONIFIED_P (f))
-           {
-             /* Gnome shell does not iconify us when C-z is pressed.
-                It hides the frame.  So if our state says we aren't
-                hidden anymore, treat it as deiconified.  */
-             SET_FRAME_VISIBLE (f, 1);
-             SET_FRAME_ICONIFIED (f, false);
-             FRAME_X_OUTPUT (f)->has_been_visible = true;
-             inev.ie.kind = DEICONIFY_EVENT;
-             XSETFRAME (inev.ie.frame_or_window, f);
-           }
-       }
-    }
-
   if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
     store_frame_param (f, Qfullscreen, Qfullboth);
   else if (new_state & GDK_WINDOW_STATE_MAXIMIZED)
@@ -5500,14 +5482,37 @@ window_state_event (GtkWidget *widget,
   else
     store_frame_param (f, Qfullscreen, Qnil);
 
+  /* The Wayland protocol provides no way for the client to know
+     whether or not one of its toplevels has actually been
+     deiconified.  It only provides a request for clients to iconify a
+     toplevel, without even the ability to determine whether or not
+     the iconification request was rejected by the display server.
+
+     GDK computes the iconified state by sending a window state event
+     containing only GDK_WINDOW_STATE_ICONIFIED immediately after
+     gtk_window_iconify is called.  That is error-prone if the request
+     to iconify the frame was rejected by the display server, but is
+     not the main problem here, as Wayland compositors only rarely
+     reject such requests.  GDK also assumes that it can clear the
+     iconified state upon receiving the next toplevel configure event
+     from the display server.  Unfortunately, such events can be sent
+     by Wayland compositors while the frame is iconified, and may also
+     not be sent upon deiconification.  So, no matter what Emacs does,
+     the iconification state of a frame is likely to be wrong under
+     one situation or another.  */
+
   if (new_state & GDK_WINDOW_STATE_ICONIFIED)
-    SET_FRAME_ICONIFIED (f, true);
+    {
+      SET_FRAME_ICONIFIED (f, true);
+      SET_FRAME_VISIBLE (f, false);
+    }
   else
     {
       FRAME_X_OUTPUT (f)->has_been_visible = true;
       inev.ie.kind = DEICONIFY_EVENT;
       XSETFRAME (inev.ie.frame_or_window, f);
       SET_FRAME_ICONIFIED (f, false);
+      SET_FRAME_VISIBLE (f, true);
     }
 
   if (new_state & GDK_WINDOW_STATE_STICKY)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]