Add background transparency support for GTK+Cairo
This commit is contained in:
parent
35cd9197fc
commit
b944841173
11 changed files with 157 additions and 15 deletions
|
@ -149,6 +149,15 @@ various X toolkits (GTK+, Lucid, etc.)---we indicate below when this
|
|||
is the case.
|
||||
|
||||
@table @asis
|
||||
@item @code{alpha} (class @code{Alpha})
|
||||
Sets the @samp{alpha} frame parameter, determining frame transparency
|
||||
(@pxref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual}).
|
||||
|
||||
@item @code{alphaBackground} (class @code{AlphaBackground})
|
||||
Sets the @samp{alpha-background} frame parameter, determining background
|
||||
transparency
|
||||
(@pxref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual}).
|
||||
|
||||
@item @code{background} (class @code{Background})
|
||||
Background color (@pxref{Colors}).
|
||||
|
||||
|
|
|
@ -2433,6 +2433,16 @@ opacity when it is not selected.
|
|||
|
||||
Some window systems do not support the @code{alpha} parameter for child
|
||||
frames (@pxref{Child Frames}).
|
||||
|
||||
@vindex alpha-background@r{, a frame parameter}
|
||||
@item alpha-background
|
||||
@cindex opacity, frame
|
||||
@cindex transparency, frame
|
||||
Sets the background transparency of the frame. Unlike the @code{alpha}
|
||||
frame parameter, this only controls the transparency of the background
|
||||
while keeping foreground elements such as text fully opaque. It
|
||||
should be an integer between 0 and 100, where 0 means
|
||||
completely transparent and 100 means completely opaque (default).
|
||||
@end table
|
||||
|
||||
The following frame parameters are semi-obsolete in that they are
|
||||
|
|
29
src/frame.c
29
src/frame.c
|
@ -3907,6 +3907,7 @@ static const struct frame_parm_table frame_parms[] =
|
|||
{"z-group", SYMBOL_INDEX (Qz_group)},
|
||||
{"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
|
||||
{"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
|
||||
{"alpha-background", SYMBOL_INDEX (Qalpha_background)},
|
||||
#ifdef NS_IMPL_COCOA
|
||||
{"ns-appearance", SYMBOL_INDEX (Qns_appearance)},
|
||||
{"ns-transparent-titlebar", SYMBOL_INDEX (Qns_transparent_titlebar)},
|
||||
|
@ -5024,6 +5025,33 @@ gui_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
gui_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
|
||||
{
|
||||
double alpha = 1.0;
|
||||
|
||||
if (NILP (arg))
|
||||
alpha = 1.0;
|
||||
else if (FLOATP (arg))
|
||||
{
|
||||
alpha = XFLOAT_DATA (arg);
|
||||
if (! (0 <= alpha && alpha <= 1.0))
|
||||
args_out_of_range (make_float (0.0), make_float (1.0));
|
||||
}
|
||||
else if (FIXNUMP (arg))
|
||||
{
|
||||
EMACS_INT ialpha = XFIXNUM (arg);
|
||||
if (! (0 <= ialpha && ialpha <= 100))
|
||||
args_out_of_range (make_fixnum (0), make_fixnum (100));
|
||||
alpha = ialpha / 100.0;
|
||||
}
|
||||
else
|
||||
wrong_type_argument (Qnumberp, arg);
|
||||
|
||||
f->alpha_background = alpha;
|
||||
|
||||
SET_FRAME_GARBAGED (f);
|
||||
}
|
||||
|
||||
/**
|
||||
* gui_set_no_special_glyphs:
|
||||
|
@ -6100,6 +6128,7 @@ syms_of_frame (void)
|
|||
#endif
|
||||
|
||||
DEFSYM (Qalpha, "alpha");
|
||||
DEFSYM (Qalpha_background, "alpha-background");
|
||||
DEFSYM (Qauto_lower, "auto-lower");
|
||||
DEFSYM (Qauto_raise, "auto-raise");
|
||||
DEFSYM (Qborder_color, "border-color");
|
||||
|
|
|
@ -637,6 +637,9 @@ struct frame
|
|||
Negative values mean not to change alpha. */
|
||||
double alpha[2];
|
||||
|
||||
/* Background opacity */
|
||||
double alpha_background;
|
||||
|
||||
/* Exponent for gamma correction of colors. 1/(VIEWING_GAMMA *
|
||||
SCREEN_GAMMA) where viewing_gamma is 0.4545 and SCREEN_GAMMA is a
|
||||
frame parameter. 0 means don't do gamma correction. */
|
||||
|
@ -1669,6 +1672,7 @@ extern void gui_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object)
|
|||
extern long gui_figure_window_size (struct frame *, Lisp_Object, bool, bool);
|
||||
|
||||
extern void gui_set_alpha (struct frame *, Lisp_Object, Lisp_Object);
|
||||
extern void gui_set_alpha_background (struct frame *, Lisp_Object, Lisp_Object);
|
||||
extern void gui_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object);
|
||||
|
||||
extern void validate_x_resource_name (void);
|
||||
|
|
|
@ -1467,6 +1467,10 @@ 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
|
||||
|
@ -1587,6 +1591,15 @@ xg_create_frame_widgets (struct frame *f)
|
|||
#endif
|
||||
| GDK_VISIBILITY_NOTIFY_MASK);
|
||||
|
||||
GdkScreen *screen = gtk_widget_get_screen (wtop);
|
||||
|
||||
if (FRAME_DISPLAY_INFO (f)->n_planes == 32)
|
||||
{
|
||||
GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
|
||||
gtk_widget_set_visual (wtop, visual);
|
||||
gtk_widget_set_visual (wfixed, visual);
|
||||
}
|
||||
|
||||
#ifndef HAVE_PGTK
|
||||
/* Must realize the windows so the X window gets created. It is used
|
||||
by callers of this function. */
|
||||
|
@ -1651,7 +1664,6 @@ xg_create_frame_widgets (struct frame *f)
|
|||
#endif
|
||||
|
||||
{
|
||||
GdkScreen *screen = gtk_widget_get_screen (wtop);
|
||||
GtkSettings *gs = gtk_settings_get_for_screen (screen);
|
||||
/* Only connect this signal once per screen. */
|
||||
if (! g_signal_handler_find (G_OBJECT (gs),
|
||||
|
|
|
@ -830,6 +830,8 @@ haiku_create_frame (Lisp_Object parms)
|
|||
RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qfullscreen, Qnil,
|
||||
"fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
|
||||
|
||||
|
@ -1043,6 +1045,8 @@ haiku_create_tip_frame (Lisp_Object parms)
|
|||
"cursorType", "CursorType", RES_TYPE_SYMBOL);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
initial_setup_back_buffer (f);
|
||||
|
||||
|
@ -2609,7 +2613,8 @@ frame_parm_handler haiku_frame_parm_handlers[] =
|
|||
haiku_set_no_accept_focus,
|
||||
NULL, /* set z group */
|
||||
haiku_set_override_redirect,
|
||||
gui_set_no_special_glyphs
|
||||
gui_set_no_special_glyphs,
|
||||
gui_set_alpha_background,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -1004,6 +1004,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
|
|||
ns_set_z_group,
|
||||
0, /* x_set_override_redirect */
|
||||
gui_set_no_special_glyphs,
|
||||
gui_set_alpha_background,
|
||||
#ifdef NS_IMPL_COCOA
|
||||
ns_set_appearance,
|
||||
ns_set_transparent_titlebar,
|
||||
|
@ -1436,6 +1437,8 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
|
|||
RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qfullscreen, Qnil,
|
||||
"fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
|
||||
|
||||
|
|
|
@ -1043,6 +1043,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = {
|
|||
x_set_z_group,
|
||||
x_set_override_redirect,
|
||||
gui_set_no_special_glyphs,
|
||||
gui_set_alpha_background,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1667,6 +1668,8 @@ This function is an internal primitive--use `make-frame' instead. */ )
|
|||
RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
if (!NILP (parent_frame))
|
||||
{
|
||||
|
@ -2936,6 +2939,8 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
|
|||
"cursorType", "CursorType", RES_TYPE_SYMBOL);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
/* Add `tooltip' frame parameter's default value. */
|
||||
if (NILP (Fframe_parameter (frame, Qtooltip)))
|
||||
|
|
|
@ -6018,6 +6018,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
|
|||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
gui_default_parameter (f, parameters, Qno_special_glyphs, Qnil,
|
||||
NULL, NULL, RES_TYPE_BOOLEAN);
|
||||
gui_default_parameter (f, parameters, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
/* Process alpha here (Bug#16619). On XP this fails with child
|
||||
frames. For `no-focus-on-map' frames delay processing of alpha
|
||||
|
@ -6155,6 +6157,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
|
|||
gui_default_parameter (f, parameters, Qz_group, Qnil,
|
||||
NULL, NULL, RES_TYPE_SYMBOL);
|
||||
|
||||
gui_default_parameter (f, parameters, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
/* Make the window appear on the frame and enable display, unless
|
||||
the caller says not to. However, with explicit parent, Emacs
|
||||
cannot control visibility, so don't try. */
|
||||
|
@ -7089,6 +7094,8 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
|
|||
/* Process alpha here (Bug#17344). */
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
/* Add `tooltip' frame parameter's default value. */
|
||||
if (NILP (Fframe_parameter (frame, Qtooltip)))
|
||||
|
@ -10436,6 +10443,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
|
|||
w32_set_z_group,
|
||||
0, /* x_set_override_redirect */
|
||||
gui_set_no_special_glyphs,
|
||||
gui_set_alpha_background,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
30
src/xfns.c
30
src/xfns.c
|
@ -4598,6 +4598,8 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
if (!NILP (parent_frame))
|
||||
{
|
||||
|
@ -6371,10 +6373,29 @@ select_visual (struct x_display_info *dpyinfo)
|
|||
int n_visuals;
|
||||
XVisualInfo *vinfo, vinfo_template;
|
||||
|
||||
dpyinfo->visual = DefaultVisualOfScreen (screen);
|
||||
|
||||
vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
|
||||
vinfo_template.screen = XScreenNumberOfScreen (screen);
|
||||
|
||||
#if defined (USE_GTK)
|
||||
/* First attempt to use 32-bit visual if available */
|
||||
|
||||
vinfo_template.depth = 32;
|
||||
|
||||
vinfo = XGetVisualInfo (dpy, VisualScreenMask | VisualDepthMask,
|
||||
&vinfo_template, &n_visuals);
|
||||
|
||||
if (n_visuals > 0)
|
||||
{
|
||||
dpyinfo->n_planes = vinfo->depth;
|
||||
dpyinfo->visual = vinfo->visual;
|
||||
XFree (vinfo);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* defined (USE_GTK) */
|
||||
|
||||
/* 32-bit visual not available, fallback to default visual */
|
||||
dpyinfo->visual = DefaultVisualOfScreen (screen);
|
||||
vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
|
||||
vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
|
||||
&vinfo_template, &n_visuals);
|
||||
if (n_visuals <= 0)
|
||||
|
@ -7232,6 +7253,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
|
|||
"cursorType", "CursorType", RES_TYPE_SYMBOL);
|
||||
gui_default_parameter (f, parms, Qalpha, Qnil,
|
||||
"alpha", "Alpha", RES_TYPE_NUMBER);
|
||||
gui_default_parameter (f, parms, Qalpha_background, Qnil,
|
||||
"alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
|
||||
|
||||
/* Add `tooltip' frame parameter's default value. */
|
||||
if (NILP (Fframe_parameter (frame, Qtooltip)))
|
||||
|
@ -8560,6 +8583,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,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
53
src/xterm.c
53
src/xterm.c
|
@ -874,12 +874,27 @@ x_set_cr_source_with_gc_background (struct frame *f, GC gc)
|
|||
{
|
||||
XGCValues xgcv;
|
||||
XColor color;
|
||||
unsigned int depth;
|
||||
|
||||
XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
|
||||
color.pixel = xgcv.background;
|
||||
|
||||
x_query_colors (f, &color, 1);
|
||||
cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
|
||||
color.green / 65535.0, color.blue / 65535.0);
|
||||
|
||||
depth = FRAME_DISPLAY_INFO (f)->n_planes;
|
||||
|
||||
if (f->alpha_background < 1.0 && depth == 32)
|
||||
{
|
||||
cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
|
||||
color.green / 65535.0, color.blue / 65535.0,
|
||||
f->alpha_background);
|
||||
|
||||
cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
|
||||
}
|
||||
else
|
||||
cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
|
||||
color.green / 65535.0, color.blue / 65535.0);
|
||||
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
|
||||
|
@ -1318,6 +1333,29 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
|
||||
{
|
||||
#ifdef USE_CAIRO
|
||||
cairo_t *cr;
|
||||
|
||||
cr = x_begin_cr_clip (f, gc);
|
||||
x_set_cr_source_with_gc_background (f, gc);
|
||||
cairo_rectangle (cr, x, y, width, height);
|
||||
cairo_fill (cr);
|
||||
x_end_cr_clip (f);
|
||||
#else
|
||||
XGCValues xgcv;
|
||||
Display *dpy = FRAME_X_DISPLAY (f);
|
||||
XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
|
||||
XSetForeground (dpy, gc, xgcv.background);
|
||||
XFillRectangle (dpy, FRAME_X_DRAWABLE (f),
|
||||
gc, x, y, width, height);
|
||||
XSetForeground (dpy, gc, xgcv.foreground);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
|
||||
{
|
||||
|
@ -1898,9 +1936,9 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
|
|||
if (face->stipple)
|
||||
XSetFillStyle (display, face->gc, FillOpaqueStippled);
|
||||
else
|
||||
XSetForeground (display, face->gc, face->background);
|
||||
XSetBackground (display, face->gc, face->background);
|
||||
|
||||
x_fill_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);
|
||||
|
||||
if (!face->stipple)
|
||||
XSetForeground (display, face->gc, face->foreground);
|
||||
|
@ -2201,12 +2239,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)
|
||||
{
|
||||
Display *display = FRAME_X_DISPLAY (s->f);
|
||||
XGCValues xgcv;
|
||||
XGetGCValues (display, s->gc, GCForeground | GCBackground, &xgcv);
|
||||
XSetForeground (display, s->gc, xgcv.background);
|
||||
x_fill_rectangle (s->f, s->gc, x, y, w, h);
|
||||
XSetForeground (display, s->gc, xgcv.foreground);
|
||||
x_clear_rectangle (s->f, s->gc, x, y, w, h);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue