]> git.eshelyaron.com Git - emacs.git/commitdiff
Redisplay "invisible" frames that are actually visible on modern X
authorPo Lu <luangruo@yahoo.com>
Mon, 26 Dec 2022 07:57:06 +0000 (15:57 +0800)
committerPo Lu <luangruo@yahoo.com>
Mon, 26 Dec 2022 07:57:48 +0000 (15:57 +0800)
* 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
src/dispnew.c
src/frame.h
src/xdisp.c
src/xfns.c
src/xterm.c
src/xterm.h

index af7f1050b763a0fa01abd144d384e24a2628e957..e6b90365e3b091eb57318458ec43b0456134236b 100644 (file)
--- 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.
+
 \f
 * Editing Changes in Emacs 30.1
 
index 5a9ba8909e3047014d63a1b3e15935905ed91e6b..b845acdcbc443fb4bae008780a92bda29ec9fa0e 100644 (file)
@@ -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;
index dcd32036b86e0a3fc4a8cbe3524582878dcfe48f..f29cc249ea8a64e5707952773f435946abb74375 100644 (file)
@@ -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)
 
index 08565d55322c73cd31628e1b33c405903026424c..8a32ce662350a67ff5b803a031500cac9e19b8fd 100644 (file)
@@ -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);
 }
 
index 668f711bdb59bee5e203aa25a4302ea98e6863a4..1cc5aec1eb4d8b6f46be90ca80bf57c7a929ac89 100644 (file)
@@ -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,
index 8e0a97899fee71ab53252888cd6084d047a25778..1eef8e7a724bafd80f83e5d78cbf2eaa6dca7658 100644 (file)
@@ -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;
 
index 832ffc172b92089583ca49bff4fb525fc5f3fd7c..f06e1ec5bc63a6deea29867f3ae509ecc8fbc5f1 100644 (file)
@@ -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)