emacs-diffs
[Top][All Lists]
Advanced

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

master cc29fab3a6: Redisplay "invisible" frames that are actually visibl


From: Po Lu
Subject: master cc29fab3a6: Redisplay "invisible" frames that are actually visible on modern X
Date: Mon, 26 Dec 2022 02:57:59 -0500 (EST)

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

    Redisplay "invisible" frames that are actually visible on modern X
    
    * etc/NEWS: Document that "invisible" frames are now redisplayed
    if the compositing manager is still displaying it as part of a
    thumbnail out of Emacs's control.
    
    * src/dispnew.c (Fredraw_display): Use FRAME_REDISPLAY_P.
    * src/frame.h (FRAME_REDISPLAY_P): New macro.
    
    * src/xdisp.c (clear_garbaged_frames, echo_area_display)
    (prepare_menu_bars, redisplay_internal, display_and_set_cursor)
    (gui_clear_cursor): Use FRAME_REDISPLAY_P to determine whether
    or not a frame should be redisplayed.
    * src/xfns.c (Fx_create_frame): Set visibility state initially.
    * src/xterm.c (handle_one_xevent): Likewise.
    * src/xterm.h (struct x_output): New field `visibility_state'.
---
 etc/NEWS      |  6 ++++++
 src/dispnew.c |  2 +-
 src/frame.h   | 14 ++++++++++++++
 src/xdisp.c   | 24 ++++++++++++------------
 src/xfns.c    |  1 +
 src/xterm.c   |  6 +++---
 src/xterm.h   | 10 ++++++++++
 7 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index af7f1050b7..e6b90365e3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -35,6 +35,12 @@ This means it should be less necessary to disable the likes 
of
 `select-active-regions' when Emacs is running over a slow network
 connection.
 
+** Emacs will now redisplay frames that are made visible by a compositor.
+This means even if `frame-visible-p' returns nil or `icon', the frame
+will be redisplayed if it is being displayed to the user by the
+compositing manager, which can happenas part of a preview for
+iconified windows.
+
 
 * Editing Changes in Emacs 30.1
 
diff --git a/src/dispnew.c b/src/dispnew.c
index 5a9ba8909e..b845acdcbc 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3188,7 +3188,7 @@ DEFUN ("redraw-display", Fredraw_display, 
Sredraw_display, 0, 0, "",
   Lisp_Object tail, frame;
 
   FOR_EACH_FRAME (tail, frame)
-    if (FRAME_VISIBLE_P (XFRAME (frame)))
+    if (FRAME_REDISPLAY_P (XFRAME (frame)))
       redraw_frame (XFRAME (frame));
 
   return Qnil;
diff --git a/src/frame.h b/src/frame.h
index dcd32036b8..f29cc249ea 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1010,6 +1010,20 @@ default_pixels_per_inch_y (void)
 /* True if frame F is currently visible.  */
 #define FRAME_VISIBLE_P(f) (f)->visible
 
+/* True if frame F should be redisplayed.  This is normally the same
+   as FRAME_VISIBLE_P (f).  Under X, frames can continue to be
+   displayed to the user by the compositing manager even if they are
+   invisible, so this also checks whether or not the frame is reported
+   visible by the X server.  */
+
+#ifndef HAVE_X_WINDOWS
+#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f))
+#else
+#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f)              \
+                             || (FRAME_X_P (f)                 \
+                                 && FRAME_X_VISIBLE (f)))
+#endif
+
 /* True if frame F is currently visible but hidden.  */
 #define FRAME_OBSCURED_P(f) ((f)->visible > 1)
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 08565d5532..8a32ce6623 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12938,7 +12938,7 @@ clear_garbaged_frames (void)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
+         if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p
                  /* It makes no sense to redraw a non-selected TTY
@@ -12987,7 +12987,7 @@ echo_area_display (bool update_frame_p)
   f = XFRAME (WINDOW_FRAME (w));
 
   /* Don't display if frame is invisible or not yet initialized.  */
-  if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
+  if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
     return;
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -13543,7 +13543,7 @@ prepare_menu_bars (void)
                     TTY frames to be completely redrawn, when there
                     are more than one of them, even though nothing
                     should be changed on display.  */
-                 || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
+                 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
            gui_consider_frame_title (frame);
        }
     }
@@ -16430,7 +16430,7 @@ redisplay_internal (void)
     {
       struct frame *f = XFRAME (frame);
 
-      if (FRAME_VISIBLE_P (f))
+      if (FRAME_REDISPLAY_P (f))
        {
          ++number_of_visible_frames;
          /* Adjust matrices for visible frames only.  */
@@ -16572,7 +16572,7 @@ redisplay_internal (void)
       && !w->update_mode_line
       && !current_buffer->clip_changed
       && !current_buffer->prevent_redisplay_optimizations_p
-      && FRAME_VISIBLE_P (XFRAME (w->frame))
+      && FRAME_REDISPLAY_P (XFRAME (w->frame))
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       && !XFRAME (w->frame)->cursor_type_changed
       && !XFRAME (w->frame)->face_change
@@ -16850,7 +16850,7 @@ redisplay_internal (void)
              if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
                FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
 
-             if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
+             if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
                {
                  /* Don't allow freeing images and faces for this
                     frame as long as the frame's update wasn't
@@ -16876,7 +16876,7 @@ redisplay_internal (void)
              if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
                FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
 
-             if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
+             if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
                {
                  /* If fonts changed on visible frame, display again.  */
                  if (f->fonts_changed)
@@ -16982,7 +16982,7 @@ redisplay_internal (void)
            }
        }
     }
-  else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
+  else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
     {
       sf->inhibit_clear_image_cache = true;
       displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
@@ -17033,7 +17033,7 @@ redisplay_internal (void)
        unrequest_sigio ();
       STOP_POLLING;
 
-      if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
+      if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
        {
           if (hscroll_retries <= MAX_HSCROLL_RETRIES
               && hscroll_windows (selected_window))
@@ -17132,7 +17132,7 @@ redisplay_internal (void)
 
       FOR_EACH_FRAME (tail, frame)
        {
-         if (XFRAME (frame)->visible)
+         if (FRAME_REDISPLAY_P (XFRAME (frame)))
            new_count++;
        }
 
@@ -33256,7 +33256,7 @@ display_and_set_cursor (struct window *w, bool on,
      windows and frames; in the latter case, the frame or window may
      be in the midst of changing its size, and x and y may be off the
      window.  */
-  if (! FRAME_VISIBLE_P (f)
+  if (! FRAME_REDISPLAY_P (f)
       || vpos >= w->current_matrix->nrows
       || hpos >= w->current_matrix->matrix_w)
     return;
@@ -33417,7 +33417,7 @@ gui_update_cursor (struct frame *f, bool on_p)
 void
 gui_clear_cursor (struct window *w)
 {
-  if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
+  if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
     update_window_cursor (w, false);
 }
 
diff --git a/src/xfns.c b/src/xfns.c
index 668f711bdb..1cc5aec1eb 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4741,6 +4741,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
   f->output_data.x->white_relief.pixel = -1;
   f->output_data.x->black_relief.pixel = -1;
+  f->output_data.x->visibility_state = VisibilityFullyObscured;
 
   fset_icon_name (f, gui_display_get_arg (dpyinfo,
                                           parms,
diff --git a/src/xterm.c b/src/xterm.c
index 8e0a97899f..1eef8e7a72 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -21743,9 +21743,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
     case VisibilityNotify:
       f = x_top_window_to_frame (dpyinfo, event->xvisibility.window);
-      if (f && (event->xvisibility.state == VisibilityUnobscured
-               || event->xvisibility.state == VisibilityPartiallyObscured))
-       SET_FRAME_VISIBLE (f, 1);
+
+      if (f)
+       FRAME_X_OUTPUT (f)->visibility_state = event->xvisibility.state;
 
       goto OTHER;
 
diff --git a/src/xterm.h b/src/xterm.h
index 832ffc172b..f06e1ec5bc 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1290,6 +1290,11 @@ struct x_output
      strictly an optimization to avoid extraneous synchronizing in
      some cases.  */
   int root_x, root_y;
+
+  /* The frame visibility state.  This starts out
+     VisibilityFullyObscured, but is set to something else in
+     handle_one_xevent.  */
+  int visibility_state;
 };
 
 enum
@@ -1408,6 +1413,11 @@ extern void x_mark_frame_dirty (struct frame *f);
 /* And its corresponding visual info.  */
 #define FRAME_X_VISUAL_INFO(f) (&FRAME_DISPLAY_INFO (f)->visual_info)
 
+/* Whether or not the frame is visible.  Do not test this alone.
+   Instead, use FRAME_REDISPLAY_P.  */
+#define FRAME_X_VISIBLE(f) (FRAME_X_OUTPUT (f)->visibility_state       \
+                           != VisibilityFullyObscured)
+
 #ifdef HAVE_XRENDER
 #define FRAME_X_PICTURE_FORMAT(f) FRAME_DISPLAY_INFO (f)->pict_format
 #define FRAME_X_PICTURE(f) ((f)->output_data.x->picture)



reply via email to

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