emacs-diffs
[Top][All Lists]
Advanced

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

master 1555453694: Implement `alpha-background' on non-Cairo builds


From: Po Lu
Subject: master 1555453694: Implement `alpha-background' on non-Cairo builds
Date: Sun, 30 Jan 2022 21:20:59 -0500 (EST)

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

    Implement `alpha-background' on non-Cairo builds
    
    * src/frame.c (gui_set_alpha_background): Recompute basic faces
    so xft face ext info gets reset.
    * src/gtkutil.c (xg_create_frame_widgets): Attach to style
    updated signal.
    (xg_update_frame_menubar): Set menu bar visual correctly.
    (xg_widget_style_updated): New function.
    
    * src/xfns.c (x_set_alpha_background): New function.
    (x_frame_parm_handlers): Use x_set_alpha_background instead.
    
    * src/xfont.c (xfont_draw):
    * src/xftfont.c (xftfont_draw): Handle `alpha-background'
    parameter.
    
    * src/xterm.c (x_xr_ensure_picture): Export function.
    (x_update_opaque_region): New function.
    (x_fill_rectangle): New parameter `respect_alpha_background'.
    All callers changed.
    (handle_one_xevent): Set opaque region on ConfigureNotify.
    (x_drop_xrender_surfaces): Set opaque region.
    (x_xrender_color_from_gc_foreground):
    (x_xrender_color_from_gc_background): Premultiply alpha with
    components if asked for.
    * src/xterm.h (struct x_display_info): New atom
    `Xatom_net_wm_opaque_region'.
---
 src/frame.c   |   1 +
 src/gtkutil.c |  42 +++++++++--
 src/xfns.c    |  22 +++++-
 src/xfont.c   |  25 +++++++
 src/xftfont.c |  39 ++++++++++-
 src/xterm.c   | 220 ++++++++++++++++++++++++++++++++++++++++++----------------
 src/xterm.h   |  12 +++-
 7 files changed, 291 insertions(+), 70 deletions(-)

diff --git a/src/frame.c b/src/frame.c
index f94dff0a60..8750fe4889 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -5050,6 +5050,7 @@ gui_set_alpha_background (struct frame *f, Lisp_Object 
arg, Lisp_Object oldval)
 
   f->alpha_background = alpha;
 
+  recompute_basic_faces (f);
   SET_FRAME_GARBAGED (f);
 }
 
diff --git a/src/gtkutil.c b/src/gtkutil.c
index ef6270dbcf..c46a2b3a6a 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -81,6 +81,10 @@ static void xg_im_context_commit (GtkIMContext *, gchar *, 
gpointer);
 static void xg_im_context_preedit_changed (GtkIMContext *, gpointer);
 static void xg_im_context_preedit_end (GtkIMContext *, gpointer);
 static bool xg_widget_key_press_event_cb (GtkWidget *, GdkEvent *, gpointer);
+
+#if GTK_CHECK_VERSION (3, 10, 0)
+static void xg_widget_style_updated (GtkWidget *, gpointer);
+#endif
 #endif
 
 #ifndef HAVE_GTK3
@@ -1460,6 +1464,13 @@ xg_create_frame_widgets (struct frame *f)
     }
   else
     wtop = gtk_window_new (type);
+
+#if GTK_CHECK_VERSION (3, 10, 0)
+  g_signal_connect (G_OBJECT (wtop), "style-updated",
+                   G_CALLBACK (xg_widget_style_updated), f);
+#endif
+
+  gtk_widget_set_app_paintable (wtop, f->alpha_background != 1.0);
 #else
   if (f->tooltip)
     {
@@ -1467,10 +1478,6 @@ xg_create_frame_widgets (struct frame *f)
     }
   wtop = gtk_window_new (type);
   gtk_widget_add_events (wtop, GDK_ALL_EVENTS_MASK);
-
-  /* This prevents GTK from painting the window's background, which
-     would interfere with transparent background in some environments */
-  gtk_widget_set_app_paintable (wtop, TRUE);
 #endif
 
   /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
@@ -4044,6 +4051,18 @@ xg_update_frame_menubar (struct frame *f)
   gtk_widget_show_all (x->menubar_widget);
   gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req);
   req.height *= xg_get_scale (f);
+
+#ifndef HAVE_PGTK
+  if (FRAME_DISPLAY_INFO (f)->n_planes == 32)
+    {
+      GdkScreen *screen = gtk_widget_get_screen (x->menubar_widget);
+      GdkVisual *visual = gdk_screen_get_system_visual (screen);
+
+      gtk_widget_realize (x->menubar_widget);
+      gtk_widget_set_visual (x->menubar_widget, visual);
+    }
+#endif
+
   if (FRAME_MENUBAR_HEIGHT (f) != (req.height * scale))
     {
       FRAME_MENUBAR_HEIGHT (f) = req.height * scale;
@@ -6390,5 +6409,20 @@ xg_filter_key (struct frame *frame, XEvent *xkey)
 
   return result;
 }
+
+#if GTK_CHECK_VERSION (3, 10, 0)
+static void
+xg_widget_style_updated (GtkWidget *widget, gpointer user_data)
+{
+  struct frame *f = user_data;
+
+  if (f->alpha_background < 1.0)
+    XChangeProperty (FRAME_X_DISPLAY (f),
+                    FRAME_X_WINDOW (f),
+                    FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+                    XA_CARDINAL, 32, PropModeReplace,
+                    NULL, 0);
+}
+#endif
 #endif
 #endif /* USE_GTK */
diff --git a/src/xfns.c b/src/xfns.c
index 7fe181fa3f..c0198fdc9d 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -727,6 +727,26 @@ x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, 
Lisp_Object old_value
   f->output_data.x->wait_for_wm = !NILP (new_value);
 }
 
+static void
+x_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+  gui_set_alpha_background (f, arg, oldval);
+
+  /* This prevents GTK from painting the window's background, which
+     interferes with transparent background in some environments */
+  gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f),
+                               f->alpha_background != 1.0);
+
+  if (f->alpha_background != 1.0)
+    {
+      XChangeProperty (FRAME_X_DISPLAY (f),
+                      FRAME_X_WINDOW (f),
+                      FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+                      XA_CARDINAL, 32, PropModeReplace,
+                      NULL, 0);
+    }
+}
+
 static void
 x_set_tool_bar_position (struct frame *f,
                          Lisp_Object new_value,
@@ -8583,7 +8603,7 @@ frame_parm_handler x_frame_parm_handlers[] =
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
-  gui_set_alpha_background,
+  x_set_alpha_background,
 };
 
 void
diff --git a/src/xfont.c b/src/xfont.c
index b5765cfa7b..7a50378a00 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -1003,6 +1003,31 @@ xfont_draw (struct glyph_string *s, int from, int to, 
int x, int y,
       unblock_input ();
     }
 
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+  if (with_background
+      && FRAME_DISPLAY_INFO (s->f)->n_planes == 32
+      && FRAME_CHECK_XR_VERSION (s->f, 0, 2))
+    {
+      x_xr_ensure_picture (s->f);
+
+      if (FRAME_X_PICTURE (s->f) != None)
+       {
+         XRenderColor xc;
+         int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
+
+         x_xr_apply_ext_clip (s->f, gc);
+         x_xrender_color_from_gc_background (s->f, gc, &xc, true);
+         XRenderFillRectangle (FRAME_X_DISPLAY (s->f),
+                               PictOpSrc, FRAME_X_PICTURE (s->f),
+                               &xc, x, y - ascent, s->width, height);
+         x_xr_reset_ext_clip (s->f);
+         x_mark_frame_dirty (s->f);
+
+         with_background = false;
+       }
+    }
+#endif
+
   if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
     {
       USE_SAFE_ALLOCA;
diff --git a/src/xftfont.c b/src/xftfont.c
index c2175d9614..1fcc0f4528 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -33,6 +33,10 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "ftfont.h"
 #include "pdumper.h"
 
+#ifdef HAVE_XRENDER
+#include <X11/extensions/Xrender.h>
+#endif
+
 #ifndef FC_LCD_FILTER
 /* Older fontconfig versions don't have FC_LCD_FILTER.  */
 # define FC_LCD_FILTER "lcdfilter"
@@ -496,7 +500,40 @@ xftfont_draw (struct glyph_string *s, int from, int to, 
int x, int y,
        height = ascent =
          s->first_glyph->slice.glyphless.lower_yoff
          - s->first_glyph->slice.glyphless.upper_yoff;
-      XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
+
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+      if (with_background
+         && FRAME_DISPLAY_INFO (s->f)->n_planes == 32
+         && FRAME_CHECK_XR_VERSION (s->f, 0, 2))
+       {
+         x_xr_ensure_picture (s->f);
+
+         if (FRAME_X_PICTURE (s->f) != None)
+           {
+             XRenderColor xc;
+             int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
+
+             if (s->num_clips > 0)
+               XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (s->f),
+                                                FRAME_X_PICTURE (s->f),
+                                                0, 0, s->clip, s->num_clips);
+             else
+               x_xr_reset_ext_clip (f);
+             x_xrender_color_from_gc_background (s->f, s->gc, &xc, true);
+             XRenderFillRectangle (FRAME_X_DISPLAY (s->f),
+                                   PictOpSrc, FRAME_X_PICTURE (s->f),
+                                   &xc, x, y - ascent, s->width, height);
+             x_xr_reset_ext_clip (f);
+             x_mark_frame_dirty (s->f);
+
+             with_background = false;
+           }
+         else
+           XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
+       }
+      else
+#endif
+       XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
     }
   code = alloca (sizeof (FT_UInt) * len);
   for (i = 0; i < len; i++)
diff --git a/src/xterm.c b/src/xterm.c
index e41319e95e..08b00f8051 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -341,6 +341,7 @@ static void x_wm_set_icon_pixmap (struct frame *, 
ptrdiff_t);
 static void x_initialize (void);
 
 static bool x_get_current_wm_state (struct frame *, Window, int *, bool *);
+static void x_update_opaque_region (struct frame *);
 
 /* Flush display of frame F.  */
 
@@ -361,6 +362,7 @@ x_flush (struct frame *f)
 static void
 x_drop_xrender_surfaces (struct frame *f)
 {
+  x_update_opaque_region (f);
   font_drop_xrender_surfaces (f);
 
 #ifdef HAVE_XRENDER
@@ -375,7 +377,7 @@ x_drop_xrender_surfaces (struct frame *f)
 }
 
 #ifdef HAVE_XRENDER
-MAYBE_UNUSED static void
+void
 x_xr_ensure_picture (struct frame *f)
 {
   if (FRAME_X_PICTURE (f) == None && FRAME_X_PICTURE_FORMAT (f))
@@ -444,6 +446,18 @@ record_event (char *locus, int type)
 
 #endif
 
+static void
+x_update_opaque_region (struct frame *f)
+{
+  if (f->alpha_background < 1.0)
+    XChangeProperty (FRAME_X_DISPLAY (f),
+                    FRAME_X_WINDOW (f),
+                    FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+                    XA_CARDINAL, 32, PropModeReplace,
+                    NULL, 0);
+}
+
+
 #if defined USE_CAIRO || defined HAVE_XRENDER
 static struct x_gc_ext_data *
 x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
@@ -1244,8 +1258,8 @@ x_cr_export_frames (Lisp_Object frames, 
cairo_surface_type_t surface_type)
 
 #endif /* USE_CAIRO */
 
-#if defined HAVE_XRENDER && !defined USE_CAIRO
-MAYBE_UNUSED static void
+#if defined HAVE_XRENDER
+void
 x_xr_apply_ext_clip (struct frame *f, GC gc)
 {
   eassert (FRAME_X_PICTURE (f) != None);
@@ -1259,7 +1273,7 @@ x_xr_apply_ext_clip (struct frame *f, GC gc)
                                     data->n_clip_rects);
 }
 
-MAYBE_UNUSED static void
+void
 x_xr_reset_ext_clip (struct frame *f)
 {
   XRenderPictureAttributes attrs = { .clip_mask = None };
@@ -1301,7 +1315,8 @@ x_reset_clip_rectangles (struct frame *f, GC gc)
 }
 
 static void
-x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
+x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
+                 bool respect_alpha_background)
 {
 #ifdef USE_CAIRO
   Display *dpy = FRAME_X_DISPLAY (f);
@@ -1339,6 +1354,29 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, 
int width, int height)
     }
   x_end_cr_clip (f);
 #else
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+  if (respect_alpha_background
+      && FRAME_DISPLAY_INFO (f)->n_planes == 32
+      && FRAME_CHECK_XR_VERSION (f, 0, 2))
+    {
+      x_xr_ensure_picture (f);
+
+      if (FRAME_X_PICTURE (f) != None)
+       {
+         XRenderColor xc;
+
+         x_xr_apply_ext_clip (f, gc);
+         x_xrender_color_from_gc_foreground (f, gc, &xc, true);
+         XRenderFillRectangle (FRAME_X_DISPLAY (f),
+                               PictOpSrc, FRAME_X_PICTURE (f),
+                               &xc, x, y, width, height);
+         x_xr_reset_ext_clip (f);
+         x_mark_frame_dirty (f);
+
+         return;
+       }
+    }
+#endif
   XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
                  gc, x, y, width, height);
 #endif
@@ -1346,7 +1384,8 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, 
int width, int height)
 
 
 static void
-x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
+x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
+                  bool respect_alpha_background)
 {
 #ifdef USE_CAIRO
   cairo_t *cr;
@@ -1357,6 +1396,30 @@ x_clear_rectangle (struct frame *f, GC gc, int x, int y, 
int width, int height)
   cairo_fill (cr);
   x_end_cr_clip (f);
 #else
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+  if (respect_alpha_background
+      && FRAME_DISPLAY_INFO (f)->n_planes == 32
+      && FRAME_CHECK_XR_VERSION (f, 0, 2))
+    {
+      x_xr_ensure_picture (f);
+
+      if (FRAME_X_PICTURE (f) != None)
+       {
+         XRenderColor xc;
+
+         x_xr_apply_ext_clip (f, gc);
+         x_xrender_color_from_gc_background (f, gc, &xc, true);
+         XRenderFillRectangle (FRAME_X_DISPLAY (f),
+                               PictOpSrc, FRAME_X_PICTURE (f),
+                               &xc, x, y, width, height);
+         x_xr_reset_ext_clip (f);
+         x_mark_frame_dirty (f);
+
+         return;
+       }
+    }
+#endif
+
   XGCValues xgcv;
   Display *dpy = FRAME_X_DISPLAY (f);
   XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
@@ -1397,7 +1460,7 @@ x_clear_window (struct frame *f)
   x_end_cr_clip (f);
 #else
 #ifndef USE_GTK
-  if (FRAME_X_DOUBLE_BUFFERED_P (f))
+  if (FRAME_X_DOUBLE_BUFFERED_P (f) || (f->alpha_background != 1.0))
 #endif
     x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
 #ifndef USE_GTK
@@ -1655,7 +1718,7 @@ x_draw_vertical_window_border (struct window *w, int x, 
int y0, int y1)
                    face->foreground);
 
 #ifdef USE_CAIRO
-  x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
+  x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0, false);
 #else
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
@@ -1688,13 +1751,13 @@ x_draw_window_divider (struct window *w, int x0, int 
x1, int y0, int y1)
     {
       XSetForeground (display, f->output_data.x->normal_gc, color_first);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x0, y0, 1, y1 - y0);
+                       x0, y0, 1, y1 - y0, false);
       XSetForeground (display, f->output_data.x->normal_gc, color);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x0 + 1, y0, x1 - x0 - 2, y1 - y0);
+                       x0 + 1, y0, x1 - x0 - 2, y1 - y0, false);
       XSetForeground (display, f->output_data.x->normal_gc, color_last);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x1 - 1, y0, 1, y1 - y0);
+                       x1 - 1, y0, 1, y1 - y0, false);
     }
   else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
     /* A horizontal divider, at least three pixels high: Draw first and
@@ -1702,13 +1765,13 @@ x_draw_window_divider (struct window *w, int x0, int 
x1, int y0, int y1)
     {
       XSetForeground (display, f->output_data.x->normal_gc, color_first);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x0, y0, x1 - x0, 1);
+                       x0, y0, x1 - x0, 1, false);
       XSetForeground (display, f->output_data.x->normal_gc, color);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x0, y0 + 1, x1 - x0, y1 - y0 - 2);
+                       x0, y0 + 1, x1 - x0, y1 - y0 - 2, false);
       XSetForeground (display, f->output_data.x->normal_gc, color_last);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x0, y1 - 1, x1 - x0, 1);
+                       x0, y1 - 1, x1 - x0, 1, false);
     }
   else
     {
@@ -1716,7 +1779,7 @@ x_draw_window_divider (struct window *w, int x0, int x1, 
int y0, int y1)
        differently.  */
       XSetForeground (display, f->output_data.x->normal_gc, color);
       x_fill_rectangle (f, f->output_data.x->normal_gc,
-                       x0, y0, x1 - x0, y1 - y0);
+                       x0, y0, x1 - x0, y1 - y0, false);
     }
 }
 
@@ -1841,10 +1904,10 @@ x_clear_under_internal_border (struct frame *f)
          GC gc = f->output_data.x->normal_gc;
 
          XSetForeground (display, gc, color);
-         x_fill_rectangle (f, gc, 0, margin, width, border);
-         x_fill_rectangle (f, gc, 0, 0, border, height);
-         x_fill_rectangle (f, gc, width - border, 0, border, height);
-         x_fill_rectangle (f, gc, 0, height - border, width, border);
+         x_fill_rectangle (f, gc, 0, margin, width, border, false);
+         x_fill_rectangle (f, gc, 0, 0, border, height, false);
+         x_fill_rectangle (f, gc, width - border, 0, border, height, false);
+         x_fill_rectangle (f, gc, 0, height - border, width, border, false);
          XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
        }
       else
@@ -1949,7 +2012,8 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row 
*row, struct draw_fring
       else
        XSetBackground (display, face->gc, face->background);
 
-      x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
+      x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
+                        true);
 
       if (!face->stipple)
        XSetForeground (display, face->gc, face->foreground);
@@ -2293,7 +2357,7 @@ x_compute_glyph_string_overhangs (struct glyph_string *s)
 static void
 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
 {
-  x_clear_rectangle (s->f, s->gc, x, y, w, h);
+  x_clear_rectangle (s->f, s->gc, x, y, w, h, true);
 }
 
 
@@ -2319,9 +2383,10 @@ x_draw_glyph_string_background (struct glyph_string *s, 
bool force_p)
          /* Fill background with a stipple pattern.  */
          XSetFillStyle (display, s->gc, FillOpaqueStippled);
          x_fill_rectangle (s->f, s->gc, s->x,
-                         s->y + box_line_width,
-                         s->background_width,
-                         s->height - 2 * box_line_width);
+                           s->y + box_line_width,
+                           s->background_width,
+                           s->height - 2 * box_line_width,
+                           false);
          XSetFillStyle (display, s->gc, FillSolid);
          s->background_filled_p = true;
        }
@@ -2416,7 +2481,8 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
                  x_fill_rectangle (s->f, s->gc, s->x,
                                    s->y + box_line_width,
                                    s->background_width,
-                                   s->height - 2 * box_line_width);
+                                   s->height - 2 * box_line_width,
+                                   false);
                  XSetFillStyle (display, s->gc, FillSolid);
                }
              else
@@ -3344,7 +3410,7 @@ x_draw_relief_rect (struct frame *f,
   if (left_p)
     {
       x_fill_rectangle (f, top_left_gc, left_x, top_y,
-                       vwidth, bottom_y + 1 - top_y);
+                       vwidth, bottom_y + 1 - top_y, false);
       if (top_p)
        corners |= 1 << CORNER_TOP_LEFT;
       if (bot_p)
@@ -3353,7 +3419,7 @@ x_draw_relief_rect (struct frame *f,
   if (right_p)
     {
       x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
-                       vwidth, bottom_y + 1 - top_y);
+                       vwidth, bottom_y + 1 - top_y, false);
       if (top_p)
        corners |= 1 << CORNER_TOP_RIGHT;
       if (bot_p)
@@ -3363,7 +3429,7 @@ x_draw_relief_rect (struct frame *f,
     {
       if (!right_p)
        x_fill_rectangle (f, top_left_gc, left_x, top_y,
-                         right_x + 1 - left_x, hwidth);
+                         right_x + 1 - left_x, hwidth, false);
       else
        x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
                                     right_x + 1 - left_x, hwidth, 1);
@@ -3372,7 +3438,7 @@ x_draw_relief_rect (struct frame *f,
     {
       if (!left_p)
        x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
-                         right_x + 1 - left_x, hwidth);
+                         right_x + 1 - left_x, hwidth, false);
       else
        x_fill_trapezoid_for_relief (f, bottom_right_gc,
                                     left_x, bottom_y + 1 - hwidth,
@@ -3380,10 +3446,10 @@ x_draw_relief_rect (struct frame *f,
     }
   if (left_p && vwidth > 1)
     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
-                     1, bottom_y + 1 - top_y);
+                     1, bottom_y + 1 - top_y, false);
   if (top_p && hwidth > 1)
     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
-                     right_x + 1 - left_x, 1);
+                     right_x + 1 - left_x, 1, false);
   if (corners)
     {
       XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
@@ -3505,21 +3571,25 @@ x_draw_box_rect (struct glyph_string *s,
 
   /* Top.  */
   x_fill_rectangle (s->f, s->gc,
-                 left_x, top_y, right_x - left_x + 1, hwidth);
+                   left_x, top_y, right_x - left_x + 1, hwidth,
+                   false);
 
   /* Left.  */
   if (left_p)
     x_fill_rectangle (s->f, s->gc,
-                   left_x, top_y, vwidth, bottom_y - top_y + 1);
+                     left_x, top_y, vwidth, bottom_y - top_y + 1,
+                     false);
 
   /* Bottom.  */
   x_fill_rectangle (s->f, s->gc,
-                 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
+                   left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth,
+                   false);
 
   /* Right.  */
   if (right_p)
     x_fill_rectangle (s->f, s->gc,
-                   right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
+                     right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1,
+                     false);
 
   XSetForeground (display, s->gc, xgcv.foreground);
   x_reset_clip_rectangles (s->f, s->gc);
@@ -3934,7 +4004,7 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int 
x, int y, int w, int h)
 
       /* Fill background with a stipple pattern.  */
       XSetFillStyle (display, s->gc, FillOpaqueStippled);
-      x_fill_rectangle (s->f, s->gc, x, y, w, h);
+      x_fill_rectangle (s->f, s->gc, x, y, w, h, false);
       XSetFillStyle (display, s->gc, FillSolid);
     }
   else
@@ -4139,7 +4209,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
            {
              /* Fill background with a stipple pattern.  */
              XSetFillStyle (display, gc, FillOpaqueStippled);
-             x_fill_rectangle (s->f, gc, x, y, w, h);
+             x_fill_rectangle (s->f, gc, x, y, w, h, true);
              XSetFillStyle (display, gc, FillSolid);
            }
          else
@@ -4147,7 +4217,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
              XGCValues xgcv;
              XGetGCValues (display, gc, GCForeground | GCBackground, &xgcv);
              XSetForeground (display, gc, xgcv.background);
-             x_fill_rectangle (s->f, gc, x, y, w, h);
+             x_fill_rectangle (s->f, gc, x, y, w, h, true);
              XSetForeground (display, gc, xgcv.foreground);
            }
 
@@ -4497,7 +4567,8 @@ x_draw_glyph_string (struct glyph_string *s)
               y = s->ybase + position;
               if (s->face->underline_defaulted_p)
                 x_fill_rectangle (s->f, s->gc,
-                                 s->x, y, decoration_width, thickness);
+                                 s->x, y, decoration_width, thickness,
+                                 false);
               else
                 {
                   Display *display = FRAME_X_DISPLAY (s->f);
@@ -4505,7 +4576,8 @@ x_draw_glyph_string (struct glyph_string *s)
                   XGetGCValues (display, s->gc, GCForeground, &xgcv);
                   XSetForeground (display, s->gc, s->face->underline_color);
                   x_fill_rectangle (s->f, s->gc,
-                                   s->x, y, decoration_width, thickness);
+                                   s->x, y, decoration_width, thickness,
+                                   false);
                   XSetForeground (display, s->gc, xgcv.foreground);
                 }
             }
@@ -4517,7 +4589,7 @@ x_draw_glyph_string (struct glyph_string *s)
 
          if (s->face->overline_color_defaulted_p)
            x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-                             decoration_width, h);
+                             decoration_width, h, false);
          else
            {
               Display *display = FRAME_X_DISPLAY (s->f);
@@ -4525,7 +4597,7 @@ x_draw_glyph_string (struct glyph_string *s)
              XGetGCValues (display, s->gc, GCForeground, &xgcv);
              XSetForeground (display, s->gc, s->face->overline_color);
              x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-                               decoration_width, h);
+                               decoration_width, h, false);
              XSetForeground (display, s->gc, xgcv.foreground);
            }
        }
@@ -4547,7 +4619,7 @@ x_draw_glyph_string (struct glyph_string *s)
 
          if (s->face->strike_through_color_defaulted_p)
            x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
-                           s->width, h);
+                             s->width, h, false);
          else
            {
               Display *display = FRAME_X_DISPLAY (s->f);
@@ -4555,7 +4627,7 @@ x_draw_glyph_string (struct glyph_string *s)
              XGetGCValues (display, s->gc, GCForeground, &xgcv);
              XSetForeground (display, s->gc, s->face->strike_through_color);
              x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
-                               decoration_width, h);
+                               decoration_width, h, false);
              XSetForeground (display, s->gc, xgcv.foreground);
            }
        }
@@ -4667,7 +4739,8 @@ x_clear_area (struct frame *f, int x, int y, int width, 
int height)
   x_end_cr_clip (f);
 #else
 #ifndef USE_GTK
-  if (FRAME_X_DOUBLE_BUFFERED_P (f))
+  if (FRAME_X_DOUBLE_BUFFERED_P (f)
+      || f->alpha_background != 1.0)
 #endif
     {
 #if defined HAVE_XRENDER && \
@@ -4677,10 +4750,10 @@ x_clear_area (struct frame *f, int x, int y, int width, 
int height)
          && FRAME_CHECK_XR_VERSION (f, 0, 2))
        {
          XRenderColor xc;
-         GC gc = f->output_data.x->reverse_gc;
+         GC gc = f->output_data.x->normal_gc;
 
          x_xr_apply_ext_clip (f, gc);
-         x_xrender_color_from_gc_foreground (f, gc, &xc);
+         x_xrender_color_from_gc_background (f, gc, &xc, true);
          XRenderFillRectangle (FRAME_X_DISPLAY (f),
                                PictOpSrc, FRAME_X_PICTURE (f),
                                &xc, x, y, width, height);
@@ -9392,6 +9465,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              f->output_data.x->has_been_visible = true;
            }
 
+         x_update_opaque_region (f);
+
           if (not_hidden && iconified)
             {
               inev.ie.kind = DEICONIFY_EVENT;
@@ -12134,8 +12209,8 @@ x_draw_bar_cursor (struct window *w, struct glyph_row 
*row, int width, enum text
            x += cursor_glyph->pixel_width - width;
 
          x_fill_rectangle (f, gc, x,
-                         WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                         width, row->height);
+                           WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                           width, row->height, false);
        }
       else /* HBAR_CURSOR */
        {
@@ -12156,7 +12231,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row 
*row, int width, enum text
          x_fill_rectangle (f, gc, x,
                            WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
                                                      row->height - width),
-                            w->phys_cursor_width - 1, width);
+                            w->phys_cursor_width - 1, width, false);
        }
 
       x_reset_clip_rectangles (f, gc);
@@ -15743,6 +15818,7 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
       ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", 
Xatom_net_wm_state_skip_taskbar)
       ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
       ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
+      ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region)
 #ifdef HAVE_XKB
       ATOM_REFS_INIT ("Meta", Xatom_Meta)
       ATOM_REFS_INIT ("Super", Xatom_Super)
@@ -16279,7 +16355,8 @@ init_xterm (void)
 
 #ifdef HAVE_XRENDER
 void
-x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor 
*color)
+x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor 
*color,
+                                   bool apply_alpha_background)
 {
   XGCValues xgcv;
   XColor xc;
@@ -16288,26 +16365,47 @@ x_xrender_color_from_gc_foreground (struct frame *f, 
GC gc, XRenderColor *color)
   xc.pixel = xgcv.foreground;
   x_query_colors (f, &xc, 1);
 
-  color->alpha = 65535;
-  color->red = xc.red;
-  color->blue = xc.blue;
-  color->green = xc.green;
+  if (color->alpha == 65535)
+    {
+      color->red = xc.red;
+      color->blue = xc.blue;
+      color->green = xc.green;
+    }
+  else
+    {
+      color->red = (xc.red * color->alpha) / 65535;
+      color->blue = (xc.blue * color->alpha) / 65535;
+      color->green = (xc.green * color->alpha) / 65535;
+    }
 }
 
 void
-x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor 
*color)
+x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor 
*color,
+                                   bool apply_alpha_background)
 {
   XGCValues xgcv;
   XColor xc;
 
   XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
-  xc.pixel = xgcv.foreground;
+  xc.pixel = xgcv.background;
   x_query_colors (f, &xc, 1);
 
-  color->alpha = 65535;
-  color->red = xc.red;
-  color->blue = xc.blue;
-  color->green = xc.green;
+  color->alpha = (apply_alpha_background
+                 ? 65535 * f->alpha_background
+                 : 65535);
+
+  if (color->alpha == 65535)
+    {
+      color->red = xc.red;
+      color->blue = xc.blue;
+      color->green = xc.green;
+    }
+  else
+    {
+      color->red = (xc.red * color->alpha) / 65535;
+      color->blue = (xc.blue * color->alpha) / 65535;
+      color->green = (xc.green * color->alpha) / 65535;
+    }
 }
 #endif
 
diff --git a/src/xterm.h b/src/xterm.h
index aa5bd2caa1..5e17d5b721 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -496,7 +496,8 @@ struct x_display_info
     Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
     Xatom_net_wm_state_sticky, Xatom_net_wm_state_above, 
Xatom_net_wm_state_below,
     Xatom_net_wm_state_hidden, Xatom_net_wm_state_skip_taskbar,
-    Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea;
+    Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea,
+    Xatom_net_wm_opaque_region;
 
   /* XSettings atoms and windows.  */
   Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -1242,8 +1243,13 @@ extern Lisp_Object x_cr_export_frames (Lisp_Object, 
cairo_surface_type_t);
 #endif
 
 #ifdef HAVE_XRENDER
-extern void x_xrender_color_from_gc_foreground (struct frame *, GC, 
XRenderColor *);
-extern void x_xrender_color_from_gc_background (struct frame *, GC, 
XRenderColor *);
+extern void x_xrender_color_from_gc_foreground (struct frame *, GC,
+                                               XRenderColor *, bool);
+extern void x_xrender_color_from_gc_background (struct frame *, GC,
+                                               XRenderColor *, bool);
+extern void x_xr_ensure_picture (struct frame *f);
+extern void x_xr_apply_ext_clip (struct frame *f, GC gc);
+extern void x_xr_reset_ext_clip (struct frame *f);
 #endif
 
 INLINE int



reply via email to

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