From 1555453694d9c2861c447b2f030b125f60e48297 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 31 Jan 2022 10:15:47 +0800 Subject: [PATCH] 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 f94dff0a607..8750fe4889c 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 ef6270dbcf8..c46a2b3a6a1 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 7fe181fa3fd..c0198fdc9d1 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 b5765cfa7b8..7a50378a006 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 c2175d96141..1fcc0f45284 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -33,6 +33,10 @@ along with GNU Emacs. If not, see . */ #include "ftfont.h" #include "pdumper.h" +#ifdef HAVE_XRENDER +#include +#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 e41319e95ec..08b00f80514 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 aa5bd2caa19..5e17d5b7215 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 -- 2.39.5