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. */
static void
x_drop_xrender_surfaces (struct frame *f)
{
+ x_update_opaque_region (f);
font_drop_xrender_surfaces (f);
#ifdef HAVE_XRENDER
}
#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))
#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)
#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);
data->n_clip_rects);
}
-MAYBE_UNUSED static void
+void
x_xr_reset_ext_clip (struct frame *f)
{
XRenderPictureAttributes attrs = { .clip_mask = None };
}
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);
}
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
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;
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);
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
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);
{
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
{
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
{
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);
}
}
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
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);
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);
}
/* 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;
}
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
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)
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)
{
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);
{
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,
}
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,
/* 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);
/* 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
{
/* 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
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);
}
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);
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);
}
}
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);
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);
}
}
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);
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);
}
}
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 && \
&& 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);
f->output_data.x->has_been_visible = true;
}
+ x_update_opaque_region (f);
+
if (not_hidden && iconified)
{
inev.ie.kind = DEICONIFY_EVENT;
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 */
{
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);
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)
#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;
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