unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Support for background transparency
@ 2021-11-04 19:45 Håkon Flatval
  2021-11-04 20:06 ` Eli Zaretskii
  2021-11-04 20:17 ` Lars Ingebrigtsen
  0 siblings, 2 replies; 47+ messages in thread
From: Håkon Flatval @ 2021-11-04 19:45 UTC (permalink / raw)
  To: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1042 bytes --]

Hi, emacs-devel!

I have implemented partial support for background transparency in Emacs. The fork, including a description in the README can be found at https://github.com/TheVaffel/emacs. This implementation has only been made for Xlib+gtk3+cairo builds.

After posting about this in the Emacs subreddit (https://www.reddit.com/r/emacs/comments/qm3tsv/i_implemented_partial_support_for_background/), it appears to me that this is a feature that is of interest to many Emacs users.

To start off, I would just like to feel the attitude towards this feature among other Emacs developers. In general, are there any with strong opinions in favor or against this feature?

As I'm completely new to the community, I'd also like some input as to how one proceeds with planning and implementation given there is interest for this to be made reality. I would be happy to work on this, but not sure I feel comfortable / knowledgable enough to do everything on my own.

Looking forward to hearing from you!

Best Regards,
Håkon Flatval

[-- Attachment #2: Type: text/html, Size: 3080 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-04 19:45 Support for background transparency Håkon Flatval
@ 2021-11-04 20:06 ` Eli Zaretskii
  2021-11-04 20:17 ` Lars Ingebrigtsen
  1 sibling, 0 replies; 47+ messages in thread
From: Eli Zaretskii @ 2021-11-04 20:06 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel

> From: Håkon Flatval <hkon20@hotmail.com>
> Date: Thu, 4 Nov 2021 19:45:03 +0000
> 
> I have implemented partial support for background transparency in Emacs. The fork, including a description
> in the README can be found at https://github.com/TheVaffel/emacs. This implementation has only been
> made for Xlib+gtk3+cairo builds. 
> 
> After posting about this in the Emacs subreddit
> (https://www.reddit.com/r/emacs/comments/qm3tsv/i_implemented_partial_support_for_background/), it
> appears to me that this is a feature that is of interest to many Emacs users.
> 
> To start off, I would just like to feel the attitude towards this feature among other Emacs developers. In
> general, are there any with strong opinions in favor or against this feature? 
> 
> As I'm completely new to the community, I'd also like some input as to how one proceeds with planning and
> implementation given there is interest for this to be made reality. I would be happy to work on this, but not
> sure I feel comfortable / knowledgable enough to do everything on my own.

Thanks, I suggest to begin by sending the changes as one or more
patches with "M-x report-emacs-bug", so that we could review and
discuss the changes on our issue tracker.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-04 19:45 Support for background transparency Håkon Flatval
  2021-11-04 20:06 ` Eli Zaretskii
@ 2021-11-04 20:17 ` Lars Ingebrigtsen
  2021-11-27 23:01   ` Håkon Flatval
  1 sibling, 1 reply; 47+ messages in thread
From: Lars Ingebrigtsen @ 2021-11-04 20:17 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I have implemented partial support for background transparency in Emacs.

Great!  It's a feature that has been requested many times.

> As I'm completely new to the community, I'd also like some input as to how
> one proceeds with planning and implementation given there is interest for
> this to be made reality. I would be happy to work on this, but not sure I feel
> comfortable / knowledgable enough to do everything on my own.

Posting the resulting patch (or a series of patches, depending on how
much code it is) is the preferred method to get code reviews.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-04 20:17 ` Lars Ingebrigtsen
@ 2021-11-27 23:01   ` Håkon Flatval
  2021-11-28  0:35     ` Sv: " arthur miller
                       ` (3 more replies)
  0 siblings, 4 replies; 47+ messages in thread
From: Håkon Flatval @ 2021-11-27 23:01 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: emacs-devel@gnu.org


[-- Attachment #1.1: Type: text/plain, Size: 2427 bytes --]

Hi again - sorry for the long radio silence.

>Posting the resulting patch (or a series of patches, depending on how
>much code it is) is the preferred method to get code reviews.

I've attached a patch that implements basic support for background transparency. I have only considered GDK+Cairo build configurations here, as a start.

I believe the gui_set_alpha_background​ function in frame.c​ should return some error message when the frame does not support 32 bits of depth, but am not sure how to do this best. I considered adding a new error code similar to the one used by wrong_type_argument​ (also called from gui_set_...​), but it seemed to be a bit excessive to create a  specific "frame-does-not-support-adequate-bit-depth"-error type when most other error types are of the more general forms "value-out-of-range" or "wrong-length-argument". Does anyone have suggestions on how to best communicate failure in setting alpha to the user?

Newbie question: I can't guarantee that this patch works perfectly with all build variations using GDK+Cairo, nor in all (desktop) environments where Emacs might be used. How, in general, is Emacs tested before release to ensure (most) such edge cases are caught?

I'm currently working on implementing this feature for other XLib-based build configurations too, offline, planning to submit another patch for those in the not-so-distant future.

Best,
Håkon Flatval

________________________________
Fra: Lars Ingebrigtsen <larsi@gnus.org>
Sendt: torsdag 4. november 2021 21:17
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Support for background transparency

Håkon Flatval <hkon20@hotmail.com> writes:

> I have implemented partial support for background transparency in Emacs.

Great!  It's a feature that has been requested many times.

> As I'm completely new to the community, I'd also like some input as to how
> one proceeds with planning and implementation given there is interest for
> this to be made reality. I would be happy to work on this, but not sure I feel
> comfortable / knowledgable enough to do everything on my own.

Posting the resulting patch (or a series of patches, depending on how
much code it is) is the preferred method to get code reviews.

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no

[-- Attachment #1.2: Type: text/html, Size: 4979 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-001.patch --]
[-- Type: text/x-patch; name="gdk-cairo-background-transparency-001.patch", Size: 10815 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 33e9606e41..220e061b1e 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3898,6 +3898,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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)},
@@ -5015,6 +5016,43 @@ 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);
+
+  if (alpha != 1.0)
+    {
+      // Abort if frame does not support 32-bit color
+      if (FRAME_TERMINAL (f)->get_frame_bit_depth == NULL ||
+	  FRAME_TERMINAL (f)->get_frame_bit_depth (f) != 32)
+	{
+	  return;
+	}
+    }
+
+  f->alpha_background = alpha;
+
+  SET_FRAME_GARBAGED (f);
+}
 
 /**
  * gui_set_no_special_glyphs:
@@ -6083,6 +6121,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");
diff --git a/src/frame.h b/src/frame.h
index cb2bad71c5..e45e0714a1 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -636,6 +636,9 @@ #define EMACS_FRAME_H
      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.  */
@@ -1658,6 +1661,7 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 9e676cd025..bfafc0481d 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1232,6 +1232,10 @@ xg_create_frame_widgets (struct frame *f)
   else
     wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
+  /* 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);
+
   /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
      has backported it to Gtk+ 2.0 and they add the resize grip for
      Gtk+ 2.0 applications also.  But it has a bug that makes Emacs loop
@@ -1339,6 +1343,16 @@ xg_create_frame_widgets (struct frame *f)
                          | GDK_STRUCTURE_MASK
                          | GDK_VISIBILITY_NOTIFY_MASK);
 
+  GdkScreen *screen = gtk_widget_get_screen (wtop);
+
+  if (FRAME_TERMINAL (f)->get_frame_bit_depth != NULL &&
+      FRAME_TERMINAL (f)->get_frame_bit_depth (f) == 32)
+    {
+      GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
+      gtk_widget_set_visual(wtop, visual);
+      gtk_widget_set_visual(wfixed, visual);
+    }
+
   /* Must realize the windows so the X window gets created.  It is used
      by callers of this function.  */
   gtk_widget_realize (wfixed);
@@ -1379,7 +1393,6 @@ xg_create_frame_widgets (struct frame *f)
   g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
 
   {
-    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),
diff --git a/src/termhooks.h b/src/termhooks.h
index 1cf9863f3a..b8572aac46 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -748,11 +748,13 @@ #define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
                                             const char *name,
                                             const char *class);
 \f
-  /* Image hooks */
+  /* Window hooks */
 #ifdef HAVE_WINDOW_SYSTEM
   /* Free the pixmap PIXMAP on F.  */
   void (*free_pixmap) (struct frame *f, Emacs_Pixmap pixmap);
 
+  /* Return bit depth supported by the terminal */
+  unsigned int (*get_frame_bit_depth) (struct frame *f);
 #endif
 \f
   /* Deletion hooks */
diff --git a/src/xfns.c b/src/xfns.c
index 5eff9f5b0f..84b47d370a 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4118,6 +4118,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -5731,17 +5733,33 @@ select_visual (struct x_display_info *dpyinfo)
     }
   else
     {
+      // First attempt to use 32-bit visual if available
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+      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;
+	}
+
+      // 32-bit visual not available, fallback to default visual
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
+
       if (n_visuals <= 0)
-	fatal ("Can't get proper X visual info");
+	  fatal ("Can't get proper X visual info");
 
       dpyinfo->n_planes = vinfo->depth;
       XFree (vinfo);
@@ -6549,6 +6567,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7878,6 +7898,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 8045470bdd..615c373cdc 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -684,9 +684,12 @@ x_set_cr_source_with_gc_background (struct frame *f, GC gc)
 
   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);
+  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);
 }
 
 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
@@ -1096,6 +1099,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)
+{
+  XGCValues xgcv;
+  Display *dpy = FRAME_X_DISPLAY (f);
+#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
+  XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
+  XSetForeground (dpy, gc, argb_from_rgb (xgcv.background, f->alpha_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)
 {
@@ -1975,12 +2001,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);
 }
 
 
@@ -14737,6 +14758,32 @@ x_delete_display (struct x_display_info *dpyinfo)
   xfree (dpyinfo);
 }
 
+/* Returns the number of bits supported by this frame's visual */
+static unsigned int
+x_get_frame_bit_depth (struct frame *f)
+{
+  Visual *visual = FRAME_X_VISUAL (f);
+  VisualID visual_id = XVisualIDFromVisual (visual);
+
+  XVisualInfo vinfo_template;
+  vinfo_template.visualid = visual_id;
+
+  long vinfo_mask = VisualIDMask;
+  int num_items;
+
+  XVisualInfo *visual_infos = XGetVisualInfo (FRAME_X_DISPLAY (f),
+					 vinfo_mask,
+					 &vinfo_template,
+					 &num_items);
+
+  if (num_items == 0) {
+    // Assume bit depth of 24 bits is always supported
+    return 24;
+  }
+
+  return visual_infos[0].depth;
+}
+
 #ifdef USE_X_TOOLKIT
 
 /* Atimer callback function for TIMER.  Called every 0.1s to process
@@ -14978,6 +15025,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->free_pixmap = x_free_pixmap;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
+  terminal->get_frame_bit_depth = x_get_frame_bit_depth;
   /* Other hooks are NULL by default.  */
 
   return terminal;

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Sv: Support for background transparency
  2021-11-27 23:01   ` Håkon Flatval
@ 2021-11-28  0:35     ` arthur miller
  2021-11-28 13:32       ` Lars Ingebrigtsen
  2021-11-28  7:41     ` Eli Zaretskii
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 47+ messages in thread
From: arthur miller @ 2021-11-28  0:35 UTC (permalink / raw)
  To: Håkon Flatval, Lars Ingebrigtsen; +Cc: emacs-devel@gnu.org


[-- Attachment #1.1: Type: text/plain, Size: 4087 bytes --]

If it is of any help, I have just rebuild master with the attached patch. It applied cleanly, but I see some artifacts. If you check the attached screenshot, there are two clocks without calendar, these are produced by Emacs with your patch. There are thin lines on the left and right edges where the default background is visible (green from dark solarized theme I use). There is also a separate frame with an eshell window and top with transparent background where those edges are also visible.

These artifacts were not present in previous version of your patch, one that was on your github since ~19 days ago. I have rebuilt from master yesterday with the previous patch rebased, which also cleanly applied, and I have posted some screenshots to this mail list yesterday where one can see similar clock widget with transparency applied without those edges. I have also attached the code for one of clocks so you can see that I have turned off fringes, borders and anything I could.

For the Clock with a calendar is a conky with conky-vision script.

By the way, why can I not see Håkans mail in Gnus? I just see like xml/http headers and stuff, not the message. I had no problems opening any other email from the list that arrived today. I had to open this one  via web browser.

Thanks for the patch & best regards

________________________________
Från: Emacs-devel <emacs-devel-bounces+arthur.miller=live.com@gnu.org> för Håkon Flatval <hkon20@hotmail.com>
Skickat: den 28 november 2021 00:01
Till: Lars Ingebrigtsen <larsi@gnus.org>
Kopia: emacs-devel@gnu.org <emacs-devel@gnu.org>
Ämne: Re: Support for background transparency

Hi again - sorry for the long radio silence.

>Posting the resulting patch (or a series of patches, depending on how
>much code it is) is the preferred method to get code reviews.

I've attached a patch that implements basic support for background transparency. I have only considered GDK+Cairo build configurations here, as a start.

I believe the gui_set_alpha_background​ function in frame.c​ should return some error message when the frame does not support 32 bits of depth, but am not sure how to do this best. I considered adding a new error code similar to the one used by wrong_type_argument​ (also called from gui_set_...​), but it seemed to be a bit excessive to create a  specific "frame-does-not-support-adequate-bit-depth"-error type when most other error types are of the more general forms "value-out-of-range" or "wrong-length-argument". Does anyone have suggestions on how to best communicate failure in setting alpha to the user?

Newbie question: I can't guarantee that this patch works perfectly with all build variations using GDK+Cairo, nor in all (desktop) environments where Emacs might be used. How, in general, is Emacs tested before release to ensure (most) such edge cases are caught?

I'm currently working on implementing this feature for other XLib-based build configurations too, offline, planning to submit another patch for those in the not-so-distant future.

Best,
Håkon Flatval

________________________________
Fra: Lars Ingebrigtsen <larsi@gnus.org>
Sendt: torsdag 4. november 2021 21:17
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Support for background transparency

Håkon Flatval <hkon20@hotmail.com> writes:

> I have implemented partial support for background transparency in Emacs.

Great!  It's a feature that has been requested many times.

> As I'm completely new to the community, I'd also like some input as to how
> one proceeds with planning and implementation given there is interest for
> this to be made reality. I would be happy to work on this, but not sure I feel
> comfortable / knowledgable enough to do everything on my own.

Posting the resulting patch (or a series of patches, depending on how
much code it is) is the preferred method to get code reviews.

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no

[-- Attachment #1.2: Type: text/html, Size: 8424 bytes --]

[-- Attachment #2: alpha-patch-screenshot-nov-28.png --]
[-- Type: image/png, Size: 515521 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: emacs-vision-clock.el --]
[-- Type: text/x-emacs-lisp; name="emacs-vision-clock.el", Size: 4577 bytes --]

;;; emacs-vision-clock.el ---  -*- lexical-binding: t; -*-

;; Copyright (C) 2021  Arthur Miller

;; Author: Arthur Miller <arthur.miller@live.com>
;; Keywords: 

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; https://github.com/BobbyBakes/conky-Vision
\f
;;; Code:
(require 'time-stamp)

(defgroup emacs-vision-clock nil
  "Conky like clock application written in Emacs Lisp."
  :prefix "evc--"
  :prefix "emacs-vision-clock-"
  :tag "Conky-Vision style clock as Emacs application."
  :group 'applications)
\f
;;; Customize
(defcustom emacs-vision-clock-x -100
  "Frame width"
  :type 'fixnum
  :group 'emacs-vision-clock)

(defcustom emacs-vision-clock-y 100
  "Frame width"
  :type 'fixnum
  :group 'emacs-vision-clock)

(defface emacs-vision-clock-date-face
  '((t :weight light :family "Poiret One" :default nil
       :foreground "white" :height 280))
  "Default face for emacs-vision-clock frame."
  :group 'emacs-vision-clock)

(defface emacs-vision-clock-time-face
  '((t :weight light :family "Poiret One" :default nil
       :foreground "white" :height 1000))
  "Default face for emacs-vision-clock frame."
  :group 'emacs-vision-clock)
\f
;;; Implementation
(defvar evc--frame nil)
(defvar evc--timer nil)
(defvar evc--buffer nil)

(defun evc--time ()
  (propertize
   (time-stamp-string "%H:%M") 'face 'emacs-vision-clock-time-face))

(defun evc--date ()
  (propertize
   (concat
    (capitalize (time-stamp-string "%A")) ". "
    (capitalize (time-stamp-string "%B %d")))
   'face 'emacs-vision-clock-date-face))

(defun evc--make-frame ()
  (make-frame `((name . "*emacs-vision-clock*")
                (left . ,emacs-vision-clock-x)
                (top . ,emacs-vision-clock-y)
                '(alpha-background . 0)
                (tool-bar-lines . 0)
                (menu-bar-lines . 0)
                (minibuffer . nil)
                (right-fringe . 0)
                (left-fringe . 0)
                (horizontal-scroll-bars . nil)
                (vertical-scroll-bars . nil)
                (border-width . 0)
                (internal-border-width . 0)
                (no-special-glyphs . t)
                (visibility . nil)
                (z-group . below)
                (auto-raise . nil)
                (skip-taskbar . t)
                (no-focus-on-map . t)
                (no-accept-focus . t)
                (unsplittable . t)
                (undecorated . t))))

(defun evc--update ()
  (let ((time (evc--time))
        (date (evc--date)))
    (when (frame-live-p evc--frame)
      (select-frame evc--frame))
    (with-current-buffer evc--buffer
      (erase-buffer)
      (let* ((tlen (* 0.5 (string-pixel-width time)))
             (dlen (* 0.5 (string-pixel-width date)))
             (spct (propertize " " 'display `(space :align-to (- center (,tlen)))))
             (spcd (propertize " " 'display `(space :align-to (- center (,dlen))))))
        (insert spct time "\n" spcd date)
        (goto-char 1)))))

(defun evc--make-buffer ()
  (with-current-buffer (get-buffer-create "  *emacs-vision-clock*")
    (setq cursor-in-non-selected-windows nil mode-line-format nil)
    (setq evc--buffer (current-buffer))))

(defun evc--make-widget ()
  (let ((frame (evc--make-frame)))
    (evc--make-buffer)
    (select-frame frame)
    (switch-to-buffer evc--buffer)
    (delete-other-windows)
    (evc--update)
    (fit-frame-to-buffer)
    (make-frame-visible frame)
    (set-window-dedicated-p (selected-window) t)
    (setq evc--frame frame evc--timer (run-at-time nil 60 #'evc--update))))
\f
;;; Public commands
(defun emacs-vision-clock-run ()
  (interactive)
  (unless evc--frame
    (evc--make-widget)))

(defun emacs-vision-clock-stop ()
  (interactive)
  (if evc--timer (cancel-timer evc--timer))
  (if evc--frame (delete-frame evc--frame))
  (if evc--buffer (kill-buffer evc--buffer))
  (setq evc--buffer nil evc--frame nil evc--timer nil))

(provide 'emacs-vision-clock)
;;; emacs-vision-clock.el ends here

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-27 23:01   ` Håkon Flatval
  2021-11-28  0:35     ` Sv: " arthur miller
@ 2021-11-28  7:41     ` Eli Zaretskii
  2021-11-28  7:47       ` Po Lu
  2021-12-01 18:54       ` Sv: " Håkon Flatval
  2021-11-28 13:41     ` Lars Ingebrigtsen
  2021-11-28 18:10     ` Jean Louis
  3 siblings, 2 replies; 47+ messages in thread
From: Eli Zaretskii @ 2021-11-28  7:41 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: larsi, emacs-devel

> From: Håkon Flatval <hkon20@hotmail.com>
> Date: Sat, 27 Nov 2021 23:01:39 +0000
> Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
> 
> I believe the gui_set_alpha_background​ function in frame.c​ should return some error message
> when the frame does not support 32 bits of depth, but am not sure how to do this best.

Why do we want an error message?  Why not simply do nothing and return
in that case?  Silently doing nothing when the display doesn't support
some feature is perfectly fine, IMO.

> Newbie question: I can't guarantee that this patch works perfectly with all build variations using GDK+Cairo,
> nor in all (desktop) environments where Emacs might be used. How, in general, is Emacs tested before
> release to ensure (most) such edge cases are caught?

We rely on people who track the development code to report any
problems they see.

> I'm currently working on implementing this feature for other XLib-based build configurations too, offline,
> planning to submit another patch for those in the not-so-distant future.

Thanks.

> +  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;
> +    }

We have XFLOATINT to do both of the above, so you could avoid
repetitions.

Also, instead of signaling an error, how about using clip_to_bounds to
limit the value to the correct range?  Once again, it is perfectly OK
to do that in display-related code, instead of signaling an error.
Moreover, signaling an error could potentially hang Emacs if this
function is called in some context where recovery is not possible.

> +  else
> +    wrong_type_argument (Qnumberp, arg);

IMO, the CHECK_NUMBER test should be up front.

> +  if (alpha != 1.0)
> +    {
> +      // Abort if frame does not support 32-bit color

I don't see any need to abort, see above.

Also, please use C-style comments, /* Like this.  */

> +      gtk_widget_set_visual(wtop, visual);
> +      gtk_widget_set_visual(wfixed, visual);
                             ^^
Our style is to leave one space between the function's name and the
opening parenthesis.

> --- a/src/termhooks.h
> +++ b/src/termhooks.h
> @@ -748,11 +748,13 @@ #define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
>                                              const char *name,
>                                              const char *class);
>  \f
> -  /* Image hooks */
> +  /* Window hooks */

I'm not sure this comment replacement is for the better.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-28  7:41     ` Eli Zaretskii
@ 2021-11-28  7:47       ` Po Lu
  2021-11-28  8:27         ` Eli Zaretskii
  2021-12-01 18:54       ` Sv: " Håkon Flatval
  1 sibling, 1 reply; 47+ messages in thread
From: Po Lu @ 2021-11-28  7:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Håkon Flatval, larsi, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> We rely on people who track the development code to report any
> problems they see.

Speaking of which, wouldn't it be better to have this as a face
attribute, like `:background-alpha' and `:foreground-alpha', instead of
as a frame parameter?

Thanks.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-28  7:47       ` Po Lu
@ 2021-11-28  8:27         ` Eli Zaretskii
  0 siblings, 0 replies; 47+ messages in thread
From: Eli Zaretskii @ 2021-11-28  8:27 UTC (permalink / raw)
  To: Po Lu; +Cc: larsi, hkon20, emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Cc: Håkon Flatval <hkon20@hotmail.com>,  larsi@gnus.org,
>   emacs-devel@gnu.org
> Date: Sun, 28 Nov 2021 15:47:00 +0800
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > We rely on people who track the development code to report any
> > problems they see.
> 
> Speaking of which, wouldn't it be better to have this as a face
> attribute, like `:background-alpha' and `:foreground-alpha', instead of
> as a frame parameter?

They are not a contradiction.  A frame parameter makes a lot of sense
for users who want the Emacs frames to have transparent background.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Support for background transparency
  2021-11-28  0:35     ` Sv: " arthur miller
@ 2021-11-28 13:32       ` Lars Ingebrigtsen
  2021-11-28 16:04         ` Arthur Miller
  0 siblings, 1 reply; 47+ messages in thread
From: Lars Ingebrigtsen @ 2021-11-28 13:32 UTC (permalink / raw)
  To: arthur miller; +Cc: Håkon Flatval, emacs-devel@gnu.org

arthur miller <arthur.miller@live.com> writes:

> By the way, why can I not see Håkans mail in Gnus? I just see like xml/http
> headers and stuff, not the message. 

It looks fine to me in Gnus.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-27 23:01   ` Håkon Flatval
  2021-11-28  0:35     ` Sv: " arthur miller
  2021-11-28  7:41     ` Eli Zaretskii
@ 2021-11-28 13:41     ` Lars Ingebrigtsen
  2021-11-28 15:05       ` Sv: " Håkon Flatval
  2021-11-28 18:10     ` Jean Louis
  3 siblings, 1 reply; 47+ messages in thread
From: Lars Ingebrigtsen @ 2021-11-28 13:41 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I've attached a patch that implements basic support for background
> transparency. I have only considered GDK+Cairo build configurations here, as a
> start.

That's really cool.  It seems to work fine here (Debian/bookworm), but
with these compilation warnings.

xterm.c: In function 'x_clear_rectangle':
xterm.c:1107:12: warning: unused variable 'dpy' [-Wunused-variable]
 1107 |   Display *dpy = FRAME_X_DISPLAY (f);
      |            ^~~
xterm.c:1106:13: warning: unused variable 'xgcv' [-Wunused-variable]
 1106 |   XGCValues xgcv;
      |             ^~~~

> Newbie question: I can't guarantee that this patch works perfectly
> with all build variations using GDK+Cairo, nor in all (desktop)
> environments where Emacs might be used. How, in general, is Emacs
> tested before release to ensure (most) such edge cases are caught?

We put the code into the development tree and wait for people to report
problems.  😀

> I'm currently working on implementing this feature for other XLib-based build
> configurations too, offline, planning to submit another patch for those in the
> not-so-distant future.

Great!

Have you started the FSF copyright assignment process?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Sv: Support for background transparency
  2021-11-28 13:41     ` Lars Ingebrigtsen
@ 2021-11-28 15:05       ` Håkon Flatval
  2021-11-28 16:07         ` Gregor Zattler
  2021-11-28 16:32         ` Lars Ingebrigtsen
  0 siblings, 2 replies; 47+ messages in thread
From: Håkon Flatval @ 2021-11-28 15:05 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 2056 bytes --]

> That's really cool.  It seems to work fine here (Debian/bookworm), but
> with these compilation warnings.

Ah, I forgot about those - I'll take care of them.

I haven't heard about the FSF Copyright Assignment Process  before.
I found some information about it online, but don't understand what
purpose it serves in this context. Do I need to follow through with it
to proceed with this contribution to Emacs?

Best,
Håkon

________________________________
Fra: Lars Ingebrigtsen <larsi@gnus.org>
Sendt: søndag 28. november 2021 14:41
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Support for background transparency

Håkon Flatval <hkon20@hotmail.com> writes:

> I've attached a patch that implements basic support for background
> transparency. I have only considered GDK+Cairo build configurations here, as a
> start.

That's really cool.  It seems to work fine here (Debian/bookworm), but
with these compilation warnings.

xterm.c: In function 'x_clear_rectangle':
xterm.c:1107:12: warning: unused variable 'dpy' [-Wunused-variable]
 1107 |   Display *dpy = FRAME_X_DISPLAY (f);
      |            ^~~
xterm.c:1106:13: warning: unused variable 'xgcv' [-Wunused-variable]
 1106 |   XGCValues xgcv;
      |             ^~~~

> Newbie question: I can't guarantee that this patch works perfectly
> with all build variations using GDK+Cairo, nor in all (desktop)
> environments where Emacs might be used. How, in general, is Emacs
> tested before release to ensure (most) such edge cases are caught?

We put the code into the development tree and wait for people to report
problems.  😀

> I'm currently working on implementing this feature for other XLib-based build
> configurations too, offline, planning to submit another patch for those in the
> not-so-distant future.

Great!

Have you started the FSF copyright assignment process?

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no

[-- Attachment #2: Type: text/html, Size: 4393 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Support for background transparency
  2021-11-28 13:32       ` Lars Ingebrigtsen
@ 2021-11-28 16:04         ` Arthur Miller
  2021-11-28 20:33           ` Håkon Flatval
  0 siblings, 1 reply; 47+ messages in thread
From: Arthur Miller @ 2021-11-28 16:04 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Håkon Flatval, emacs-devel@gnu.org

Lars Ingebrigtsen <larsi@gnus.org> writes:

> arthur miller <arthur.miller@live.com> writes:
>
>> By the way, why can I not see Håkans mail in Gnus? I just see like xml/http
>> headers and stuff, not the message. 
>
> It looks fine to me in Gnus.

I saw another one litlle bit earlie, and found it was my setting I changes like yesterday :).

I tested to use w3m for html renderer, and latre commented away setting, but I
didn't restarted Emacs. I am not sure if I byte compiled my nit or not after, so
it might have been that. Works now.

Btw I have also pulled and rebuild the Emacs today and I don't see those lines
today.




^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Support for background transparency
  2021-11-28 15:05       ` Sv: " Håkon Flatval
@ 2021-11-28 16:07         ` Gregor Zattler
  2021-11-28 16:32         ` Lars Ingebrigtsen
  1 sibling, 0 replies; 47+ messages in thread
From: Gregor Zattler @ 2021-11-28 16:07 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Hi Håkon,
* Håkon Flatval <hkon20@hotmail.com> [2021-11-28; 15:05]:
> I haven't heard about the FSF Copyright Assignment Process  before.
> I found some information about it online, but don't understand what
> purpose it serves in this context. 

short:
https://www.gnu.org/licenses/why-assign.html

long:
https://www.fsf.org/blogs/licensing/FSF-copyright-handling

> Do I need to follow through with it to proceed with this
> contribution to Emacs?

Yes.

"Once the cumulative amount of your submissions exceeds a dozen or so
lines of non-trivial changes, we will need you to assign to the FSF
the copyright for your contributions."


"In most cases, to start the assignment process you should download
https://git.savannah.gnu.org/cgit/gnulib.git/plain/doc/Copyright/request-assign.future
and return the completed information to the address at the top."

(both from CONTRIBUTE in emacs top level source directory).





Ciao; Gregor
-- 
 -... --- .-. . -.. ..--.. ...-.-



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Support for background transparency
  2021-11-28 15:05       ` Sv: " Håkon Flatval
  2021-11-28 16:07         ` Gregor Zattler
@ 2021-11-28 16:32         ` Lars Ingebrigtsen
  1 sibling, 0 replies; 47+ messages in thread
From: Lars Ingebrigtsen @ 2021-11-28 16:32 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I haven't heard about the FSF Copyright Assignment Process  before. 
> I found some information about it online, but don't understand what
> purpose it serves in this context. Do I need to follow through with it
> to proceed with this contribution to Emacs?

Yes, all non-trivial code changes to Emacs has to have the copyright
assigned to the FSF.  Read here for more info:

  https://www.gnu.org/licenses/why-assign.en.html

If that's OK, this is the form to get started:

Please email the following information to assign@gnu.org, and we
will send you the assignment form for your past and future changes.

Please use your full legal name (in ASCII characters) as the subject
line of the message.
----------------------------------------------------------------------
REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES

[What is the name of the program or package you're contributing to?]
Emacs

[Did you copy any files or text written by someone else in these changes?
Even if that material is free software, we need to know about it.]

[Do you have an employer who might have a basis to claim to own
your changes?  Do you attend a school which might make such a claim?]

[For the copyright registration, what country are you a citizen of?]

[What year were you born?]

[Please write your email address here.]

[Please write your postal address here.]

[Which files have you changed so far, and which new files have you written
so far?]



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Support for background transparency
  2021-11-27 23:01   ` Håkon Flatval
                       ` (2 preceding siblings ...)
  2021-11-28 13:41     ` Lars Ingebrigtsen
@ 2021-11-28 18:10     ` Jean Louis
  2021-11-28 18:44       ` Sv: " Håkon Flatval
  3 siblings, 1 reply; 47+ messages in thread
From: Jean Louis @ 2021-11-28 18:10 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: Lars Ingebrigtsen, emacs-devel@gnu.org

* Håkon Flatval <hkon20@hotmail.com> [2021-11-28 02:21]:
> Hi again - sorry for the long radio silence.
> 
> >Posting the resulting patch (or a series of patches, depending on how
> >much code it is) is the preferred method to get code reviews.
> 
> I've attached a patch that implements basic support for background
> transparency. I have only considered GDK+Cairo build configurations
> here, as a start.

Is it going to work for:

GNU Emacs 29.0.50 (build 3, x86_64-pc-linux-gnu, X toolkit, cairo version 1.17.4, Xaw3d scroll bars)

Where I use Lucid build?


-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

In support of Richard M. Stallman
https://stallmansupport.org/



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Sv: Support for background transparency
  2021-11-28 18:10     ` Jean Louis
@ 2021-11-28 18:44       ` Håkon Flatval
  0 siblings, 0 replies; 47+ messages in thread
From: Håkon Flatval @ 2021-11-28 18:44 UTC (permalink / raw)
  To: Jean Louis; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1452 bytes --]

Hi!

Currently, it is only made to work with builds using GDK and Cairo together.
Thus, it will probably not work with Lucid.

However, I'm working on more broad support for other X-toolkit based builds.
Some partial implementation of this support is already up in my fork: https://github.com/TheVaffel/emacs
You can have a sneak peek at that if you're eager to try it, although it's work in progress.

Best,
Håkon

________________________________
Fra: Jean Louis <bugs@gnu.support>
Sendt: søndag 28. november 2021 19:10
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: Lars Ingebrigtsen <larsi@gnus.org>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Support for background transparency

* Håkon Flatval <hkon20@hotmail.com> [2021-11-28 02:21]:
> Hi again - sorry for the long radio silence.
>
> >Posting the resulting patch (or a series of patches, depending on how
> >much code it is) is the preferred method to get code reviews.
>
> I've attached a patch that implements basic support for background
> transparency. I have only considered GDK+Cairo build configurations
> here, as a start.

Is it going to work for:

GNU Emacs 29.0.50 (build 3, x86_64-pc-linux-gnu, X toolkit, cairo version 1.17.4, Xaw3d scroll bars)

Where I use Lucid build?


--
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

In support of Richard M. Stallman
https://stallmansupport.org/

[-- Attachment #2: Type: text/html, Size: 3927 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Sv: Support for background transparency
  2021-11-28 16:04         ` Arthur Miller
@ 2021-11-28 20:33           ` Håkon Flatval
  2021-11-29  2:56             ` Arthur Miller
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2021-11-28 20:33 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1166 bytes --]

> Btw I have also pulled and rebuild the Emacs today and I don't see those lines
> today.

Ok, I really struggled to reproduce those lines by myself - glad the issue seems to be gone. Hope it doesn't return.

- Håkon

________________________________
Fra: Arthur Miller <arthur.miller@live.com>
Sendt: søndag 28. november 2021 17:04
Til: Lars Ingebrigtsen <larsi@gnus.org>
Kopi: Håkon Flatval <hkon20@hotmail.com>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Sv: Support for background transparency

Lars Ingebrigtsen <larsi@gnus.org> writes:

> arthur miller <arthur.miller@live.com> writes:
>
>> By the way, why can I not see Håkans mail in Gnus? I just see like xml/http
>> headers and stuff, not the message.
>
> It looks fine to me in Gnus.

I saw another one litlle bit earlie, and found it was my setting I changes like yesterday :).

I tested to use w3m for html renderer, and latre commented away setting, but I
didn't restarted Emacs. I am not sure if I byte compiled my nit or not after, so
it might have been that. Works now.

Btw I have also pulled and rebuild the Emacs today and I don't see those lines
today.


[-- Attachment #2: Type: text/html, Size: 2787 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Support for background transparency
  2021-11-28 20:33           ` Håkon Flatval
@ 2021-11-29  2:56             ` Arthur Miller
  0 siblings, 0 replies; 47+ messages in thread
From: Arthur Miller @ 2021-11-29  2:56 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

>> Btw I have also pulled and rebuild the Emacs today and I don't see those lines
>> today.
>
> Ok, I really struggled to reproduce those lines by myself - glad the issue seems to be gone. Hope it doesn't return.

Sorry for giving you worries. :)

The patch seem to work very well so far.

>
> - Håkon
>  
>
> -------------------------------------------------------------------------------------------------------------------------
> Fra: Arthur Miller <arthur.miller@live.com>
> Sendt: søndag 28. november 2021 17:04
> Til: Lars Ingebrigtsen <larsi@gnus.org>
> Kopi: Håkon Flatval <hkon20@hotmail.com>; emacs-devel@gnu.org <emacs-devel@gnu.org>
> Emne: Re: Sv: Support for background transparency 
>  
> Lars Ingebrigtsen <larsi@gnus.org> writes:
>
>> arthur miller <arthur.miller@live.com> writes:
>>
>>> By the way, why can I not see Håkans mail in Gnus? I just see like xml/http
>>> headers and stuff, not the message. 
>>
>> It looks fine to me in Gnus.
>
> I saw another one litlle bit earlie, and found it was my setting I changes like yesterday :).
>
> I tested to use w3m for html renderer, and latre commented away setting, but I
> didn't restarted Emacs. I am not sure if I byte compiled my nit or not after, so
> it might have been that. Works now.
>
> Btw I have also pulled and rebuild the Emacs today and I don't see those lines
> today.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Sv: Support for background transparency
  2021-11-28  7:41     ` Eli Zaretskii
  2021-11-28  7:47       ` Po Lu
@ 2021-12-01 18:54       ` Håkon Flatval
  2021-12-09 17:13         ` Håkon Flatval
  1 sibling, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2021-12-01 18:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Lars Ingebrigtsen, emacs-devel@gnu.org


[-- Attachment #1.1: Type: text/plain, Size: 3985 bytes --]

Hi again, and thanks for reviewing.

I have addressed most of your comments in this new patch.

However, I have not changed the way the input argument is handled in gui_set_alpha_background​. You proposed using XFLOATINT​, but as far as I understand, it will return the exact value of the input argument. I want the input to be interpreted as a ratio (0 - 1) if the value is a float and a percentage (0 - 100) if the value is an integer. This is how the arguments are intepreted in gui_set_alpha​ in frame.c​, which I have tried to mimick when creating this function. Please do tell if you disagree with this decision.

In addition, I have corrected the compiler warnings reported by Lars, as well as a couple of errors which would prevent compilation / create strange behavior for builds not using Cairo.

Best,
Håkon

________________________________
Fra: Eli Zaretskii <eliz@gnu.org>
Sendt: søndag 28. november 2021 08:41
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: larsi@gnus.org <larsi@gnus.org>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Support for background transparency

> From: Håkon Flatval <hkon20@hotmail.com>
> Date: Sat, 27 Nov 2021 23:01:39 +0000
> Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
>
> I believe the gui_set_alpha_background​ function in frame.c​ should return some error message
> when the frame does not support 32 bits of depth, but am not sure how to do this best.

Why do we want an error message?  Why not simply do nothing and return
in that case?  Silently doing nothing when the display doesn't support
some feature is perfectly fine, IMO.

> Newbie question: I can't guarantee that this patch works perfectly with all build variations using GDK+Cairo,
> nor in all (desktop) environments where Emacs might be used. How, in general, is Emacs tested before
> release to ensure (most) such edge cases are caught?

We rely on people who track the development code to report any
problems they see.

> I'm currently working on implementing this feature for other XLib-based build configurations too, offline,
> planning to submit another patch for those in the not-so-distant future.

Thanks.

> +  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;
> +    }

We have XFLOATINT to do both of the above, so you could avoid
repetitions.

Also, instead of signaling an error, how about using clip_to_bounds to
limit the value to the correct range?  Once again, it is perfectly OK
to do that in display-related code, instead of signaling an error.
Moreover, signaling an error could potentially hang Emacs if this
function is called in some context where recovery is not possible.

> +  else
> +    wrong_type_argument (Qnumberp, arg);

IMO, the CHECK_NUMBER test should be up front.

> +  if (alpha != 1.0)
> +    {
> +      // Abort if frame does not support 32-bit color

I don't see any need to abort, see above.

Also, please use C-style comments, /* Like this.  */

> +      gtk_widget_set_visual(wtop, visual);
> +      gtk_widget_set_visual(wfixed, visual);
                             ^^
Our style is to leave one space between the function's name and the
opening parenthesis.

> --- a/src/termhooks.h
> +++ b/src/termhooks.h
> @@ -748,11 +748,13 @@ #define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
>                                              const char *name,
>                                              const char *class);
>
> -  /* Image hooks */
> +  /* Window hooks */

I'm not sure this comment replacement is for the better.

[-- Attachment #1.2: Type: text/html, Size: 7312 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-002.patch --]
[-- Type: text/x-patch; name="gdk-cairo-background-transparency-002.patch", Size: 9304 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 33e9606e41..e9a4c1edc3 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3898,6 +3898,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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)},
@@ -5015,6 +5016,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:
@@ -6083,6 +6111,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");
diff --git a/src/frame.h b/src/frame.h
index cb2bad71c5..e45e0714a1 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -636,6 +636,9 @@ #define EMACS_FRAME_H
      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.  */
@@ -1658,6 +1661,7 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 9e676cd025..ab99392596 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -195,6 +195,27 @@ xg_get_scale (struct frame *f)
   return xg_get_gdk_scale ();
 }
 
+static unsigned int
+x_get_bit_depth (struct frame *f)
+{
+  Visual *visual = FRAME_X_VISUAL (f);
+  VisualID visual_id = XVisualIDFromVisual (visual);
+
+  XVisualInfo vinfo_template;
+  vinfo_template.visualid = visual_id;
+
+  int num_items;
+
+  XVisualInfo *visual_infos = XGetVisualInfo (FRAME_X_DISPLAY (f),
+					      VisualIDMask,
+					      &vinfo_template,
+					      &num_items);
+
+  eassert (num_items > 0);
+
+  return visual_infos[0].depth;
+}
+
 /* Close display DPY.  */
 
 void
@@ -1232,6 +1253,10 @@ xg_create_frame_widgets (struct frame *f)
   else
     wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
+  /* 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);
+
   /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
      has backported it to Gtk+ 2.0 and they add the resize grip for
      Gtk+ 2.0 applications also.  But it has a bug that makes Emacs loop
@@ -1339,6 +1364,15 @@ xg_create_frame_widgets (struct frame *f)
                          | GDK_STRUCTURE_MASK
                          | GDK_VISIBILITY_NOTIFY_MASK);
 
+  GdkScreen *screen = gtk_widget_get_screen (wtop);
+
+  if (x_get_bit_depth (f) == 32)
+    {
+      GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
+      gtk_widget_set_visual (wtop, visual);
+      gtk_widget_set_visual (wfixed, visual);
+    }
+
   /* Must realize the windows so the X window gets created.  It is used
      by callers of this function.  */
   gtk_widget_realize (wfixed);
@@ -1379,7 +1413,6 @@ xg_create_frame_widgets (struct frame *f)
   g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
 
   {
-    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),
diff --git a/src/xfns.c b/src/xfns.c
index 5eff9f5b0f..6660d725a6 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4118,6 +4118,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -5734,14 +5736,35 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO)
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
+
       if (n_visuals <= 0)
-	fatal ("Can't get proper X visual info");
+	  fatal ("Can't get proper X visual info");
 
       dpyinfo->n_planes = vinfo->depth;
       XFree (vinfo);
@@ -6549,6 +6572,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7878,6 +7903,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 8045470bdd..2a4556a8fd 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -684,9 +684,12 @@ x_set_cr_source_with_gc_background (struct frame *f, GC gc)
 
   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);
+  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);
 }
 
 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
@@ -1096,6 +1099,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)
 {
@@ -1975,12 +2001,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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Sv: Support for background transparency
  2021-12-01 18:54       ` Sv: " Håkon Flatval
@ 2021-12-09 17:13         ` Håkon Flatval
  2021-12-10  0:40           ` Lars Ingebrigtsen
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2021-12-09 17:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Lars Ingebrigtsen, emacs-devel@gnu.org


[-- Attachment #1.1: Type: text/plain, Size: 4436 bytes --]

I eventually decided that it makes sense for the fringe to be considered background, i.e. be rendered transparent as well. I've included it in this patch.

Håkon

________________________________
Fra: Håkon Flatval <hkon20@hotmail.com>
Sendt: onsdag 1. desember 2021 19:54
Til: Eli Zaretskii <eliz@gnu.org>
Kopi: emacs-devel@gnu.org <emacs-devel@gnu.org>; Lars Ingebrigtsen <larsi@gnus.org>
Emne: Sv: Support for background transparency

Hi again, and thanks for reviewing.

I have addressed most of your comments in this new patch.

However, I have not changed the way the input argument is handled in gui_set_alpha_background​. You proposed using XFLOATINT​, but as far as I understand, it will return the exact value of the input argument. I want the input to be interpreted as a ratio (0 - 1) if the value is a float and a percentage (0 - 100) if the value is an integer. This is how the arguments are intepreted in gui_set_alpha​ in frame.c​, which I have tried to mimick when creating this function. Please do tell if you disagree with this decision.

In addition, I have corrected the compiler warnings reported by Lars, as well as a couple of errors which would prevent compilation / create strange behavior for builds not using Cairo.

Best,
Håkon

________________________________
Fra: Eli Zaretskii <eliz@gnu.org>
Sendt: søndag 28. november 2021 08:41
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: larsi@gnus.org <larsi@gnus.org>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Support for background transparency

> From: Håkon Flatval <hkon20@hotmail.com>
> Date: Sat, 27 Nov 2021 23:01:39 +0000
> Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
>
> I believe the gui_set_alpha_background​ function in frame.c​ should return some error message
> when the frame does not support 32 bits of depth, but am not sure how to do this best.

Why do we want an error message?  Why not simply do nothing and return
in that case?  Silently doing nothing when the display doesn't support
some feature is perfectly fine, IMO.

> Newbie question: I can't guarantee that this patch works perfectly with all build variations using GDK+Cairo,
> nor in all (desktop) environments where Emacs might be used. How, in general, is Emacs tested before
> release to ensure (most) such edge cases are caught?

We rely on people who track the development code to report any
problems they see.

> I'm currently working on implementing this feature for other XLib-based build configurations too, offline,
> planning to submit another patch for those in the not-so-distant future.

Thanks.

> +  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;
> +    }

We have XFLOATINT to do both of the above, so you could avoid
repetitions.

Also, instead of signaling an error, how about using clip_to_bounds to
limit the value to the correct range?  Once again, it is perfectly OK
to do that in display-related code, instead of signaling an error.
Moreover, signaling an error could potentially hang Emacs if this
function is called in some context where recovery is not possible.

> +  else
> +    wrong_type_argument (Qnumberp, arg);

IMO, the CHECK_NUMBER test should be up front.

> +  if (alpha != 1.0)
> +    {
> +      // Abort if frame does not support 32-bit color

I don't see any need to abort, see above.

Also, please use C-style comments, /* Like this.  */

> +      gtk_widget_set_visual(wtop, visual);
> +      gtk_widget_set_visual(wfixed, visual);
                             ^^
Our style is to leave one space between the function's name and the
opening parenthesis.

> --- a/src/termhooks.h
> +++ b/src/termhooks.h
> @@ -748,11 +748,13 @@ #define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
>                                              const char *name,
>                                              const char *class);
>
> -  /* Image hooks */
> +  /* Window hooks */

I'm not sure this comment replacement is for the better.

[-- Attachment #1.2: Type: text/html, Size: 8427 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-003.patch --]
[-- Type: text/x-patch; name="gdk-cairo-background-transparency-003.patch", Size: 9836 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 33e9606e41..e9a4c1edc3 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3898,6 +3898,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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)},
@@ -5015,6 +5016,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:
@@ -6083,6 +6111,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");
diff --git a/src/frame.h b/src/frame.h
index cb2bad71c5..e45e0714a1 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -636,6 +636,9 @@ #define EMACS_FRAME_H
      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.  */
@@ -1658,6 +1661,7 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 8f8db4ed37..17d93e504e 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -195,6 +195,27 @@ xg_get_scale (struct frame *f)
   return xg_get_gdk_scale ();
 }
 
+static unsigned int
+x_get_bit_depth (struct frame *f)
+{
+  Visual *visual = FRAME_X_VISUAL (f);
+  VisualID visual_id = XVisualIDFromVisual (visual);
+
+  XVisualInfo vinfo_template;
+  vinfo_template.visualid = visual_id;
+
+  int num_items;
+
+  XVisualInfo *visual_infos = XGetVisualInfo (FRAME_X_DISPLAY (f),
+					      VisualIDMask,
+					      &vinfo_template,
+					      &num_items);
+
+  eassert (num_items > 0);
+
+  return visual_infos[0].depth;
+}
+
 /* Close display DPY.  */
 
 void
@@ -1236,6 +1257,10 @@ xg_create_frame_widgets (struct frame *f)
   else
     wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
+  /* 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);
+
   /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
      has backported it to Gtk+ 2.0 and they add the resize grip for
      Gtk+ 2.0 applications also.  But it has a bug that makes Emacs loop
@@ -1343,6 +1368,15 @@ xg_create_frame_widgets (struct frame *f)
                          | GDK_STRUCTURE_MASK
                          | GDK_VISIBILITY_NOTIFY_MASK);
 
+  GdkScreen *screen = gtk_widget_get_screen (wtop);
+
+  if (x_get_bit_depth (f) == 32)
+    {
+      GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
+      gtk_widget_set_visual (wtop, visual);
+      gtk_widget_set_visual (wfixed, visual);
+    }
+
   /* Must realize the windows so the X window gets created.  It is used
      by callers of this function.  */
   gtk_widget_realize (wfixed);
@@ -1383,7 +1417,6 @@ xg_create_frame_widgets (struct frame *f)
   g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
 
   {
-    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),
diff --git a/src/xfns.c b/src/xfns.c
index 5eff9f5b0f..6660d725a6 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4118,6 +4118,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -5734,14 +5736,35 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO)
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
+
       if (n_visuals <= 0)
-	fatal ("Can't get proper X visual info");
+	  fatal ("Can't get proper X visual info");
 
       dpyinfo->n_planes = vinfo->depth;
       XFree (vinfo);
@@ -6549,6 +6572,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7878,6 +7903,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index ae0daa79f3..e6e71982a0 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -684,9 +684,12 @@ x_set_cr_source_with_gc_background (struct frame *f, GC gc)
 
   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);
+  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);
 }
 
 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
@@ -1096,6 +1099,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)
 {
@@ -1672,9 +1698,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);
@@ -1975,12 +2001,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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Support for background transparency
  2021-12-09 17:13         ` Håkon Flatval
@ 2021-12-10  0:40           ` Lars Ingebrigtsen
  2022-01-19 17:26             ` Sv: " Håkon Flatval
  0 siblings, 1 reply; 47+ messages in thread
From: Lars Ingebrigtsen @ 2021-12-10  0:40 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: Eli Zaretskii, emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I eventually decided that it makes sense for the fringe to be
> considered background, i.e. be rendered transparent as well. I've
> included it in this patch.

I tried the patch here (Debian/bookworm), and it works great.  So I
guess we just have to wait until the copyright assignment process has
completed?  

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Sv: Sv: Support for background transparency
  2021-12-10  0:40           ` Lars Ingebrigtsen
@ 2022-01-19 17:26             ` Håkon Flatval
  2022-01-20  0:52               ` Po Lu
  2022-01-20  9:12               ` Robert Pluim
  0 siblings, 2 replies; 47+ messages in thread
From: Håkon Flatval @ 2022-01-19 17:26 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: emacs-devel@gnu.org


[-- Attachment #1.1: Type: text/plain, Size: 1115 bytes --]

Hi again,

At long last the copyright assignment process is finished.

I have attached a final patch. The only changes from the last one is a small conflict resolution I did while rebasing today.

Is everything ready to have it merged? And also, how does that happen? Is the ball in your court, or does it require action on my end?

Best,
Håkon

________________________________
Fra: Lars Ingebrigtsen <larsi@gnus.org>
Sendt: fredag 10. desember 2021 01:40
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: Eli Zaretskii <eliz@gnu.org>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Sv: Support for background transparency

Håkon Flatval <hkon20@hotmail.com> writes:

> I eventually decided that it makes sense for the fringe to be
> considered background, i.e. be rendered transparent as well. I've
> included it in this patch.

I tried the patch here (Debian/bookworm), and it works great.  So I
guess we just have to wait until the copyright assignment process has
completed?

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no

[-- Attachment #1.2: Type: text/html, Size: 3060 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-004.patch --]
[-- Type: text/x-patch; name="gdk-cairo-background-transparency-004.patch", Size: 9725 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 3cb8cd1533..ab3b3cc8d8 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -231,6 +231,27 @@ xg_get_scale (struct frame *f)
   return xg_get_gdk_scale ();
 }
 
+static unsigned int
+x_get_bit_depth (struct frame *f)
+{
+  Visual *visual = FRAME_X_VISUAL (f);
+  VisualID visual_id = XVisualIDFromVisual (visual);
+
+  XVisualInfo vinfo_template;
+  vinfo_template.visualid = visual_id;
+
+  int num_items;
+
+  XVisualInfo *visual_infos = XGetVisualInfo (FRAME_X_DISPLAY (f),
+					      VisualIDMask,
+					      &vinfo_template,
+					      &num_items);
+
+  eassert (num_items > 0);
+
+  return visual_infos[0].depth;
+}
+
 /* Close display DPY.  */
 
 void
@@ -1469,6 +1490,10 @@ xg_create_frame_widgets (struct frame *f)
   gtk_widget_add_events (wtop, GDK_ALL_EVENTS_MASK);
 #endif
 
+  /* 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);
+
   /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
      has backported it to Gtk+ 2.0 and they add the resize grip for
      Gtk+ 2.0 applications also.  But it has a bug that makes Emacs loop
@@ -1587,6 +1612,15 @@ xg_create_frame_widgets (struct frame *f)
 #endif
                          | GDK_VISIBILITY_NOTIFY_MASK);
 
+  GdkScreen *screen = gtk_widget_get_screen (wtop);
+
+  if (x_get_bit_depth (f) == 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 +1685,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),
diff --git a/src/xfns.c b/src/xfns.c
index a1435d5351..7fcc5e2c3f 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4569,6 +4569,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -6342,14 +6344,35 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO)
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
+
       if (n_visuals <= 0)
-	fatal ("Can't get proper X visual info");
+	  fatal ("Can't get proper X visual info");
 
       dpyinfo->n_planes = vinfo->depth;
       XFree (vinfo);
@@ -7203,6 +7226,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -8531,6 +8556,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index d3619f5b5e..7df20daff8 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -837,9 +837,12 @@ x_set_cr_source_with_gc_background (struct frame *f, GC gc)
 
   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);
+  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);
 }
 
 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
@@ -1252,6 +1255,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)
 {
@@ -1828,9 +1854,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);
@@ -2131,12 +2157,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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-19 17:26             ` Sv: " Håkon Flatval
@ 2022-01-20  0:52               ` Po Lu
  2022-01-20 19:52                 ` Sv: " Håkon Flatval
  2022-01-20  9:12               ` Robert Pluim
  1 sibling, 1 reply; 47+ messages in thread
From: Po Lu @ 2022-01-20  0:52 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: Lars Ingebrigtsen, emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:


> I have attached a final patch. The only changes from the last one is a
> small conflict resolution I did while rebasing today.
>
> Is everything ready to have it merged? And also, how does that happen?
> Is the ball in your court, or does it require action on my end?

I see some problems:

> +  /* 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);

This must be under the conditional `!HAVE_PGTK'.

> +#if defined (USE_GTK) && defined (USE_CAIRO)

Why only Cairo?  I see no reason this can't work on non-Cairo
configurations, or Cairo configurations built without GTK.

> +  gui_set_alpha_background,

In this case, please add the frame parameter handler to the rest of the
terminal backends, even if it doesn't do anything:

  - pgtkfns.c
  - nsfns.c
  - w32fns.c
  - haikufns.c

> +                         color.green / 65535.0, color.blue / 65535.0, f->alpha_background);
> +
> +  cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);

Cairo on XCB becomes _very_ slow if this is done and the visual has no
alpha channel, so please make this conditional on both alpha being less
than 1.0 and the display's visual actually having an alpha channel.

Also, I see a hunk that only touches indentation and whitespace.  Please
remove the following whitespace-only change:

> +
>        vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
>  			      &vinfo_template, &n_visuals);
> +
>        if (n_visuals <= 0)
> -	fatal ("Can't get proper X visual info");
> +	  fatal ("Can't get proper X visual info");

Aside from that, LGTM.  Thanks.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-19 17:26             ` Sv: " Håkon Flatval
  2022-01-20  0:52               ` Po Lu
@ 2022-01-20  9:12               ` Robert Pluim
  2022-01-23 21:43                 ` Håkon Flatval
  1 sibling, 1 reply; 47+ messages in thread
From: Robert Pluim @ 2022-01-20  9:12 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: Lars Ingebrigtsen, emacs-devel@gnu.org

>>>>> On Wed, 19 Jan 2022 17:26:26 +0000, Håkon Flatval <hkon20@hotmail.com> said:

    Håkon> Hi again,
    Håkon> At long last the copyright assignment process is finished.

    Håkon> I have attached a final patch. The only changes from the last one is a
    Håkon> small conflict resolution I did while rebasing today.

Apart from Po's technical concerns, there are two things missing:

- a commit message containing a description of the changes in
ChangeLog format ('C-x 4 a' can help with that)
- Something answering the question: "what's the difference between
this and the existing 'alpha frame parameter", ideally in the emacs
lisp reference manual (alpha described in (elisp)Frame Parameters).

    Håkon> Is everything ready to have it merged? And also, how does that happen?
    Håkon> Is the ball in your court, or does it require action on my end?

Once the patch looks good someone here will merge it.

Robert
-- 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Sv: Sv: Sv: Support for background transparency
  2022-01-20  0:52               ` Po Lu
@ 2022-01-20 19:52                 ` Håkon Flatval
  2022-01-21  0:59                   ` Po Lu
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-20 19:52 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel@gnu.org


[-- Attachment #1.1: Type: text/plain, Size: 2865 bytes --]

Thanks for the thorough review!

I have adressed your points in this new patch.

I now run a check on the bit depth of the visual in the x_set_cr_source_with_gc_background function. I'm not too happy about this solution, as it involves two more calls to the X API, but perhaps it is acceptable.

I have primarily considered GTK and Cairo when implementing this. Support for other build configurations do not work currently. It will require additional treatment of e.g. the LUCID libs. I have looked a bit on such builds on the side, but currently have not shaped a plan to finish it.

The preprocessor statements are to ensure nothing else is screwed up when using 32-bit visuals.

Again, I appreciate the feedback.

Best regards,
Håkon

________________________________
Fra: Po Lu <luangruo@yahoo.com>
Sendt: torsdag 20. januar 2022 01:52
Til: Håkon Flatval <hkon20@hotmail.com>
Kopi: Lars Ingebrigtsen <larsi@gnus.org>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Emne: Re: Sv: Sv: Support for background transparency

Håkon Flatval <hkon20@hotmail.com> writes:


> I have attached a final patch. The only changes from the last one is a
> small conflict resolution I did while rebasing today.
>
> Is everything ready to have it merged? And also, how does that happen?
> Is the ball in your court, or does it require action on my end?

I see some problems:

> +  /* 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);

This must be under the conditional `!HAVE_PGTK'.

> +#if defined (USE_GTK) && defined (USE_CAIRO)

Why only Cairo?  I see no reason this can't work on non-Cairo
configurations, or Cairo configurations built without GTK.

> +  gui_set_alpha_background,

In this case, please add the frame parameter handler to the rest of the
terminal backends, even if it doesn't do anything:

  - pgtkfns.c
  - nsfns.c
  - w32fns.c
  - haikufns.c

> +                         color.green / 65535.0, color.blue / 65535.0, f->alpha_background);
> +
> +  cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);

Cairo on XCB becomes _very_ slow if this is done and the visual has no
alpha channel, so please make this conditional on both alpha being less
than 1.0 and the display's visual actually having an alpha channel.

Also, I see a hunk that only touches indentation and whitespace.  Please
remove the following whitespace-only change:

> +
>        vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
>                              &vinfo_template, &n_visuals);
> +
>        if (n_visuals <= 0)
> -     fatal ("Can't get proper X visual info");
> +       fatal ("Can't get proper X visual info");

Aside from that, LGTM.  Thanks.

[-- Attachment #1.2: Type: text/html, Size: 5879 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-005.patch --]
[-- Type: text/x-patch; name="gdk-cairo-background-transparency-005.patch", Size: 11809 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 3cb8cd1533..bd34999630 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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 (x_get_bit_depth (f) == 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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..7117296a73 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -2609,7 +2609,8 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..a4f3f091fc 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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,
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..b46429379e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
diff --git a/src/w32fns.c b/src/w32fns.c
index 37f9b813c6..a360faefa8 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10436,6 +10436,7 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index a1435d5351..fca2badb79 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4569,6 +4569,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -6342,10 +6344,29 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO)
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
       if (n_visuals <= 0)
@@ -7203,6 +7224,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -8531,6 +8554,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 5adbf210be..507dae670e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -836,12 +836,24 @@ 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 = x_get_bit_depth (f);
+
+  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;
@@ -1254,6 +1266,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)
 {
@@ -1830,9 +1865,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);
@@ -2133,12 +2168,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);
 }
 
 
@@ -4019,6 +4049,27 @@ x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
     }
 }
 
+unsigned int
+x_get_bit_depth (struct frame *f)
+{
+  Visual *visual = FRAME_X_VISUAL (f);
+  VisualID visual_id = XVisualIDFromVisual (visual);
+
+  XVisualInfo vinfo_template;
+  vinfo_template.visualid = visual_id;
+
+  int num_items;
+
+  XVisualInfo *visual_infos = XGetVisualInfo (FRAME_X_DISPLAY (f),
+					      VisualIDMask,
+					      &vinfo_template,
+					      &num_items);
+
+  eassert (num_items > 0);
+
+  return visual_infos[0].depth;
+}
+
 /*
    Draw a wavy line under S. The wave fills wave_height pixels from y0.
 
diff --git a/src/xterm.h b/src/xterm.h
index 26b2851590..7899d4f264 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1155,6 +1155,7 @@ #define SELECTION_EVENT_TIME(eventp)	\
 typedef void (*x_special_error_handler)(Display *, XErrorEvent *, char *,
 					void *);
 
+extern unsigned int x_get_bit_depth (struct frame *f);
 extern bool x_text_icon (struct frame *, const char *);
 extern void x_catch_errors (Display *);
 extern void x_catch_errors_with_handler (Display *, x_special_error_handler,

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-20 19:52                 ` Sv: " Håkon Flatval
@ 2022-01-21  0:59                   ` Po Lu
  2022-01-23 13:48                     ` Håkon Flatval
  0 siblings, 1 reply; 47+ messages in thread
From: Po Lu @ 2022-01-21  0:59 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I now run a check on the bit depth of the visual in the
> x_set_cr_source_with_gc_background function. I'm not too happy about
> this solution, as it involves two more calls to the X API, but perhaps
> it is acceptable.

You could just check dpyinfo->n_planes, which should suffice (and avoid
the calls to `XGetVisualInfo').

> +  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);
> +  }

This coding style is not what we use in Emacs.  You can look at the
surrounding code and
https://www.gnu.org/prep/standards/standards.html#Formatting for more
details on how such braces should be formatted.

> I have primarily considered GTK and Cairo when implementing
> this. Support for other build configurations do not work currently.

Would you mind if I implemented that support instead?

> It will require additional treatment of e.g. the LUCID libs. I have
> looked a bit on such builds on the side, but currently have not shaped
> a plan to finish it.

The Xt builds are unlikely to ever work with this, since I couldn't find
a way to create the shell widget with a 32 bit visual, and we can only
draw into a child window (which isn't composited) on those builds
anyway.  But I do want the non-Cairo GTK and no-toolkit builds to work.

> The preprocessor statements are to ensure nothing else is screwed up
> when using 32-bit visuals.

Which preprocessor statements are you referring to?

Aside from that, I'm happy now.  Thanks for working on this often
requested (and thus important) feature.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-21  0:59                   ` Po Lu
@ 2022-01-23 13:48                     ` Håkon Flatval
  2022-01-24  0:11                       ` Po Lu
  2022-01-24 10:22                       ` Po Lu
  0 siblings, 2 replies; 47+ messages in thread
From: Håkon Flatval @ 2022-01-23 13:48 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 979 bytes --]


> This coding style is not what we use in Emacs.

Seems like I was in a bit of a rush with the formatting. It should be
in order now.

> You could just check dpyinfo->n_planes,

I was not aware of that one - simplifies things a bit. I have removed my
custom depth querying function and opted for that one instead.

> Which preprocessor statements are you referring to?

Sorry for not being specific - I was talking about the section with
>> #if defined (USE_GTK) && defined (USE_CAIRO)
that you mentioned in your previous mail. Its purpose is just to avoid
using 32-bit visuals in build configurations I have not considered, as I
know that at least some of those configurations display artifacts when
they are run with 32-bit visuals.

> Would you mind if I implemented that support instead?

I would be grateful if you would do that, as I doubt I will be able to
work on this consistently going forward.

Again, thanks for the feedback.

- Håkon


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-006.patch --]
[-- Type: text/x-patch, Size: 10694 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index eb14856062..19dd04523e 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..7117296a73 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -2609,7 +2609,8 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..a4f3f091fc 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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,
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..b46429379e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
diff --git a/src/w32fns.c b/src/w32fns.c
index 37f9b813c6..a360faefa8 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10436,6 +10436,7 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index 7123198724..a79462b125 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4569,6 +4569,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -6342,10 +6344,29 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO)
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
       if (n_visuals <= 0)
@@ -7203,6 +7224,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -8531,6 +8554,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 2a4ea883bc..08f6369ca7 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -840,12 +840,26 @@ 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;
@@ -1258,6 +1272,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)
 {
@@ -1838,9 +1875,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);
@@ -2141,12 +2178,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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-20  9:12               ` Robert Pluim
@ 2022-01-23 21:43                 ` Håkon Flatval
  2022-01-24  9:14                   ` Robert Pluim
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-23 21:43 UTC (permalink / raw)
  To: Robert Pluim; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 2285 bytes --]


> - Something answering the question: "what's the difference between
> this and the existing 'alpha frame parameter",

I added paragraph after that for alpha with a brief description.
I have included it in the attached patch. For convenience, I'm
reciting the relevant part here:

====
   diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
   index 2eeb8b7ed7..05d0b1a72a 100644
   --- a/doc/lispref/frames.texi
   +++ b/doc/lispref/frames.texi
   @@ -2433,6 +2433,16 @@ Font and Color Parameters

    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
====

Please let me know if this is what you had in mind or if I should revise
it.

> - a commit message containing a description of the changes in
> ChangeLog format

I have attached a file with a changelog entry. I'm also giving it here
for convenience:

====
   2022-01-23  Håkon Flatval  <hkon20@hotmail.com>
   	Add support for background transparency

   	* src/haikufns.c:
   	* src/nsfns.m:
   	* src/pgtkfns.c:
   	* src/w32fns.c:
   	* src/xfns.c: Add alpha-background frame parameter defaults. Prefer to use 32-bit depth visual in X.
   	* src/frame.h:
   	* src/frame.c: Add alpha-background frame parameter and setter function.
   	* src/gtkutil.c: Setup GTK to allow transparency.
   	* src/xterm.c: Draw background transparent using alpha-background frame parameter.
   	* doc/lispref/frames.texi: Add docs for alpha-background frame parameter
====

Let me know if it needs changes.

I'm a little confused as to where I should put this. Should I add it to
one of the Changelog files?

Best regards,
Håkon


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-007.patch --]
[-- Type: text/x-patch, Size: 11558 bytes --]

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 2eeb8b7ed7..05d0b1a72a 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2433,6 +2433,16 @@ Font and Color Parameters
 
 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
diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index eb14856062..19dd04523e 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..7117296a73 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -2609,7 +2609,8 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..a4f3f091fc 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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,
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..b46429379e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
diff --git a/src/w32fns.c b/src/w32fns.c
index 37f9b813c6..a360faefa8 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10436,6 +10436,7 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index 7123198724..a79462b125 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4569,6 +4569,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          RES_TYPE_NUMBER);
   gui_default_parameter (f, parms, Qalpha, Qnil,
                          "alpha", "Alpha", RES_TYPE_NUMBER);
+  gui_default_parameter (f, parms, Qalpha_background, Qnil,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   if (!NILP (parent_frame))
     {
@@ -6342,10 +6344,29 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO)
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
       if (n_visuals <= 0)
@@ -7203,6 +7224,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,
+			 "alpha_background", "AlphaBackground", RES_TYPE_NUMBER);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -8531,6 +8554,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 2a4ea883bc..ed3b9a8b25 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -840,12 +840,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;
@@ -1258,6 +1273,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)
 {
@@ -1838,9 +1876,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);
@@ -2141,12 +2179,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);
 }
 
 

[-- Attachment #3: alpha-background-changelog --]
[-- Type: application/octet-stream, Size: 562 bytes --]

2022-01-23  Håkon Flatval  <hkon20@hotmail.com>
	Add support for background transparency

	* src/haikufns.c:
	* src/nsfns.m:
	* src/pgtkfns.c:
	* src/w32fns.c:
	* src/xfns.c: Add alpha-background frame parameter defaults. Prefer to use 32-bit depth visual in X.
	* src/frame.h:
	* src/frame.c: Add alpha-background frame parameter and setter function.
	* src/gtkutil.c: Setup GTK to allow transparency.
	* src/xterm.c: Draw background transparent using alpha-background frame parameter.
	* doc/lispref/frames.texi: Add docs for alpha-background frame parameter

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-23 13:48                     ` Håkon Flatval
@ 2022-01-24  0:11                       ` Po Lu
  2022-01-25 17:53                         ` Håkon Flatval
  2022-01-24 10:22                       ` Po Lu
  1 sibling, 1 reply; 47+ messages in thread
From: Po Lu @ 2022-01-24  0:11 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> that you mentioned in your previous mail. Its purpose is just to avoid
> using 32-bit visuals in build configurations I have not considered, as I
> know that at least some of those configurations display artifacts when
> they are run with 32-bit visuals.

Could you please elaborate as to which artifacts you refer to?  Because
that's something which "shouldn't happen".  Thanks in advance.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-23 21:43                 ` Håkon Flatval
@ 2022-01-24  9:14                   ` Robert Pluim
  2022-01-25 20:00                     ` Håkon Flatval
  0 siblings, 1 reply; 47+ messages in thread
From: Robert Pluim @ 2022-01-24  9:14 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

>>>>> On Sun, 23 Jan 2022 22:43:04 +0100, Håkon Flatval <hkon20@hotmail.com> said:

    >> - Something answering the question: "what's the difference between
    >> this and the existing 'alpha frame parameter",

    Håkon> I added paragraph after that for alpha with a brief description.
    Håkon> I have included it in the attached patch. For convenience, I'm
    Håkon> reciting the relevant part here:

    Håkon> ====
    Håkon>    diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
    Håkon>    index 2eeb8b7ed7..05d0b1a72a 100644
    Håkon>    --- a/doc/lispref/frames.texi
    Håkon>    +++ b/doc/lispref/frames.texi
    Håkon>    @@ -2433,6 +2433,16 @@ Font and Color Parameters

    Håkon>     Some window systems do not support the @code{alpha} parameter for child
    Håkon>     frames (@pxref{Child Frames}).
    Håkon>    +
    Håkon>    +@vindex alpha-background@r{, a frame parameter}
    Håkon>    +@item alpha-background
    Håkon>    +@cindex opacity, frame
    Håkon>    +@cindex transparency, frame
    Håkon>    +Sets the background transparency of the frame. Unlike the @code{alpha}
    Håkon>    +frame parameter, this only controls the transparency of the background
    Håkon>    +while keeping foreground elements such as text fully opaque.
    Håkon>    +It should be an integer between 0 and 100, where 0 means
    Håkon>    +completely transparent and 100 means completely opaque (default).
    Håkon>     @end table

    Håkon>     The following frame parameters are semi-obsolete in that they are
    Håkon> ====

    Håkon> Please let me know if this is what you had in mind or if I should revise
    Håkon> it.

That looks good, although the Emacs convention is to put two spaces
after '.'

    >> - a commit message containing a description of the changes in
    >> ChangeLog format

    Håkon> I have attached a file with a changelog entry. I'm also giving it here
    Håkon> for convenience:

    Håkon> ====
    Håkon>    2022-01-23  Håkon Flatval  <hkon20@hotmail.com>
    Håkon>    	Add support for background transparency

    Håkon>    	* src/haikufns.c:
    Håkon>    	* src/nsfns.m:
    Håkon>    	* src/pgtkfns.c:
    Håkon>    	* src/w32fns.c:
    Håkon>    	* src/xfns.c: Add alpha-background frame parameter defaults. Prefer to use 32-bit depth visual in X.
    Håkon>    	* src/frame.h:
    Håkon>    	* src/frame.c: Add alpha-background frame parameter and setter function.
    Håkon>    	* src/gtkutil.c: Setup GTK to allow transparency.
    Håkon>    	* src/xterm.c: Draw background transparent using alpha-background frame parameter.
    Håkon>    	* doc/lispref/frames.texi: Add docs for alpha-background frame parameter
    Håkon> ====

    Håkon> Let me know if it needs changes.

Each filename should also have the name of the affected function in
parens after it (before the ':'). C-x 4 a when in a diff will fill in
this kind of stuff for you automatically (or
'magit-generate-changelog' if you use magit to commit).

    Håkon> I'm a little confused as to where I should put this. Should I add it to
    Håkon> one of the Changelog files?

It goes in the commit message when you commit locally using git. See
CONTRIBUTE in the emacs repository (search for "** Commit messages")

Committing locally has the additional advantage that you can later do
"git format-patch" to produce a patch file, which is easy for the
maintainers to apply (and preserves your commit message and authorship
info).

Robert
-- 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-23 13:48                     ` Håkon Flatval
  2022-01-24  0:11                       ` Po Lu
@ 2022-01-24 10:22                       ` Po Lu
  2022-01-25 19:47                         ` Håkon Flatval
  1 sibling, 1 reply; 47+ messages in thread
From: Po Lu @ 2022-01-24 10:22 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> Seems like I was in a bit of a rush with the formatting. It should be
> in order now.

BTW, this parameter should be set during frame creation, so you should
add something along the lines of what is done with
`gui_default_parameter' in Fx_create_frame in each of the terminal
specific *fns.c files.

The resource and class names should then be documented under
(emacs)Table of Resources in the user manual.

Thanks in advance.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-24  0:11                       ` Po Lu
@ 2022-01-25 17:53                         ` Håkon Flatval
  2022-01-26  1:00                           ` Po Lu
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-25 17:53 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel@gnu.org


> Could you please elaborate as to which artifacts you refer to?

When I remove the "#if defined (USE_GTK) && defined (USE_CAIRO)"
preprocessor statement in src/xfns.c and then configure with
--without-cairo, I see some visual artifacts in the result. For
instance, when marking text, the marked region becomes transparent
(without even having set the alpha-background parameter yet).

If I instead configure with --with-x-toolkit=lucid, Emacs outright
crashes on startup with the message
"X protocol error: BadMatch (invalid parameter attributes) on protocol request 70".

I get no such error on these two build configurations when the
preprocessor statement is in place.

I tested this using i3 wm on Gentoo.

In time I would like to see background transparency supported for other
configurations as well, but leaving the preprocessor statements in seems
like the easiest way to avoid havoc.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-25 20:00                     ` Håkon Flatval
@ 2022-01-25 19:31                       ` Robert Pluim
  2022-01-29 10:26                         ` Po Lu
  0 siblings, 1 reply; 47+ messages in thread
From: Robert Pluim @ 2022-01-25 19:31 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

>>>>> On Tue, 25 Jan 2022 21:00:50 +0100, Håkon Flatval <hkon20@hotmail.com> said:

    Håkon> I see - I suppose it's about time I learnt using Magit.

Itʼs not mandatory, but it frees up space in your head for things
other than git :-)

    Håkon> I have attached a new changelog, partially generated from the local
    Håkon> diff which should better fit the requirements.

    >> That looks good, although the Emacs convention is to put two spaces
    >> after '.'

    Håkon> I have corrected this in the latest patch sent to Po Lu.

That looks a lot better, thanks. One minor comment below

    Håkon> Do tell if it needs more changes.

    Håkon> - Håkon

    Håkon> 2022-01-25  Håkon Flatval  <hkon20@hotmail.com>

    Håkon> 	* src/xterm.c (x_set_cr_source_with_gc_background):
    Håkon>         Add support for transparent drawing.
    Håkon>         (x_clear_rectangle):
    Håkon>         New function for drawing with background colors.
    Håkon> 	(x_draw_rectangle):
    Håkon>         Use x_clear_rectangle function for drawing background.


    Håkon> 	* src/xfns.c (Fx_create_frame): Add alpha-background defaults.
    Håkon> 	(x_create_tip_frame): Add alpha-background defaults.
    Håkon> 	(x_frame_parm_handlers): Add alpha-background handler.

When making the same entry for multiple functions in the same file,
you can combine them:

* src/xfns.c (Fx_create_frame, x_create_tip_frame): Add
alpha-background defaults.
(x_frame_parm_handlers): Add alpha-background handler.

Robert
-- 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-25 19:47                         ` Håkon Flatval
@ 2022-01-25 19:37                           ` Robert Pluim
  2022-01-26 18:16                             ` Håkon Flatval
  2022-01-26  1:05                           ` Po Lu
  1 sibling, 1 reply; 47+ messages in thread
From: Robert Pluim @ 2022-01-25 19:37 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: Po Lu, emacs-devel@gnu.org

>>>>> On Tue, 25 Jan 2022 20:47:37 +0100, Håkon Flatval <hkon20@hotmail.com> said:

    Håkon> I also notice that it would be very handy with some link to the lispref
    Håkon> describing the frame parameters from these sections, but I don't suppose
    Håkon> that's easily doable.

You mean link from the Emacs user manual to the lispref? Something
like this will work:

(@pxref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual})

Robert
-- 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-24 10:22                       ` Po Lu
@ 2022-01-25 19:47                         ` Håkon Flatval
  2022-01-25 19:37                           ` Robert Pluim
  2022-01-26  1:05                           ` Po Lu
  0 siblings, 2 replies; 47+ messages in thread
From: Håkon Flatval @ 2022-01-25 19:47 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 766 bytes --]


> BTW, this parameter should be set during frame creation

I have put `gui_default_parameter` calls in the relevant *fns-files.
I ended up putting it in wherever the 'alpha' frame parameter is set.

> The resource and class names should then be documented under
> (emacs)Table of Resources in the user manual.

I've added it with a very brief description. I noticed that the alpha
frame parameter is not mentioned there, although it is also accessible
through an X resource. I took the liberty to add it there, also with a
very brief explanation. Do tell if it should be left for another commit.

I also notice that it would be very handy with some link to the lispref
describing the frame parameters from these sections, but I don't suppose
that's easily doable.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdk-cairo-background-transparency-008.patch --]
[-- Type: text/x-patch, Size: 16085 bytes --]

diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index ccf7e35eee..e2a1948637 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -149,6 +149,14 @@ Table of Resources
 is the case.
 
 @table @asis
+@item @code{alpha} (class @code{Alpha})
+Frame transparency. A value between 0 (full transparency) and 100
+(no transparency).
+
+@item @code{alphaBackground} (class @code{AlphaBackground})
+Background transparency. A value between 0 (full background
+transparency) and 0 (no background transparency).
+
 @item @code{background} (class @code{Background})
 Background color (@pxref{Colors}).
 
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 2eeb8b7ed7..16748ac922 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2433,6 +2433,16 @@ Font and Color Parameters
 
 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
diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index eb14856062..19dd04523e 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..0e0cffea72 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -830,6 +830,8 @@ #define ASSIGN_CURSOR(cursor, be_cursor) \
 			 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 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..467e56ece4 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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);
 
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..5980b31d6e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
@@ -1667,6 +1668,8 @@ #define INSTALL_CURSOR(FIELD, NAME) \
 			 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)))
diff --git a/src/w32fns.c b/src/w32fns.c
index 37f9b813c6..39c4d47d02 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -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 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index 33d8d98e70..303f9b0770 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4591,6 +4591,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          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))
     {
@@ -6364,10 +6366,29 @@ select_visual (struct x_display_info *dpyinfo)
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
 
-      dpyinfo->visual = DefaultVisualOfScreen (screen);
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO) */
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
 			      &vinfo_template, &n_visuals);
       if (n_visuals <= 0)
@@ -7225,6 +7246,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)))
@@ -8553,6 +8576,7 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index bf611db6bc..51c320771a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -858,12 +858,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;
@@ -1302,6 +1317,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)
 {
@@ -1882,9 +1920,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);
@@ -2185,12 +2223,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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-24  9:14                   ` Robert Pluim
@ 2022-01-25 20:00                     ` Håkon Flatval
  2022-01-25 19:31                       ` Robert Pluim
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-25 20:00 UTC (permalink / raw)
  To: Robert Pluim; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 373 bytes --]


I see - I suppose it's about time I learnt using Magit.
I have attached a new changelog, partially generated from the local
diff which should better fit the requirements.

> That looks good, although the Emacs convention is to put two spaces
> after '.'

I have corrected this in the latest patch sent to Po Lu.

Do tell if it needs more changes.

- Håkon


[-- Attachment #2: alpha-background-changelog --]
[-- Type: application/octet-stream, Size: 1863 bytes --]

2022-01-25  Håkon Flatval  <hkon20@hotmail.com>

	* src/xterm.c (x_set_cr_source_with_gc_background):
        Add support for transparent drawing.
        (x_clear_rectangle):
        New function for drawing with background colors.
	(x_draw_rectangle):
        Use x_clear_rectangle function for drawing background.


	* src/xfns.c (Fx_create_frame): Add alpha-background defaults.
	(x_create_tip_frame): Add alpha-background defaults.
	(x_frame_parm_handlers): Add alpha-background handler.

	* src/w32fns.c (Fx_create_frame): Add alpha-background defaults.
	(Fx_create_frame): Add alpha-background defaults.
	(w32_create_tip_frame): Add alpha-background defaults.
	(w32_frame_parm_handlers): Add alpha-background handler.

	* src/pgtkfns.c (pgtk_frame_parm_handlers):
        Add alpha-background handler.
	(Fx_create_frame): Add alpha-background defaults.
	(x_create_tip_frame): Add alpha-background defaults.

	* src/nsfns.m (ns_frame_parm_handlers): Add alpha-background handler.
	(Fx_create_frame): Add alpha-background defaults.

	* src/haikufns.c (haiku_create_frame): Add alpha-background defaults.
	(haiku_create_tip_frame): Add alpha-background defaults.
        (haiku_frame_parm_handlers): Add alpha-background handler.


	* src/gtkutil.c (xg_create_frame_widgets):
        Prevent GTK from filling in background.
	(xg_create_frame_widgets): Add support for 32-bit visual.


	* src/frame.h (GCALIGNED_STRUCT): Add alpha_background field.


	* src/frame.c (frame_parms): Add alpha-background frame parameter.
	(gui_set_alpha_background):
        Add gui function for setting alpha-background.
	(syms_of_frame): Add symbol for alpha-background.

	* doc/lispref/frames.texi (Font and Color Parameters):
        Add documentation on alpha-background.

	* doc/emacs/xresources.texi (Table of Resources):
	List alpha and alpha-background as X resources.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-25 17:53                         ` Håkon Flatval
@ 2022-01-26  1:00                           ` Po Lu
  0 siblings, 0 replies; 47+ messages in thread
From: Po Lu @ 2022-01-26  1:00 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> When I remove the "#if defined (USE_GTK) && defined (USE_CAIRO)"
> preprocessor statement in src/xfns.c and then configure with
> --without-cairo, I see some visual artifacts in the result. For
> instance, when marking text, the marked region becomes transparent
> (without even having set the alpha-background parameter yet).

I installed most of the code that can be used to resolve that on master
several days ago.

> If I instead configure with --with-x-toolkit=lucid, Emacs outright
> crashes on startup with the message
> "X protocol error: BadMatch (invalid parameter attributes) on protocol request 70".

Could you run Emacs like this:

    ./emacs -q -xrm 'Emacs.synchronous: true'

And show a backtrace in GDB from the crash?  Thanks.

> I get no such error on these two build configurations when the
> preprocessor statement is in place.
>
> I tested this using i3 wm on Gentoo.
>
> In time I would like to see background transparency supported for other
> configurations as well, but leaving the preprocessor statements in seems
> like the easiest way to avoid havoc.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-25 19:47                         ` Håkon Flatval
  2022-01-25 19:37                           ` Robert Pluim
@ 2022-01-26  1:05                           ` Po Lu
  2022-01-26 11:11                             ` Robert Pluim
  2022-01-26 18:34                             ` Håkon Flatval
  1 sibling, 2 replies; 47+ messages in thread
From: Po Lu @ 2022-01-26  1:05 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

>> BTW, this parameter should be set during frame creation
>
> I have put `gui_default_parameter` calls in the relevant *fns-files.
> I ended up putting it in wherever the 'alpha' frame parameter is set.

[...]

> I've added it with a very brief description. I noticed that the alpha
> frame parameter is not mentioned there, although it is also accessible
> through an X resource. I took the liberty to add it there, also with a
> very brief explanation. Do tell if it should be left for another commit.

That looks good to me now, but I'd like to know why the Lucid build
crashes with a 32-bit visual.  After that, and if Robert is happy, I'll
install it on master and implement the support for non-Cairo builds.

Thanks.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-26  1:05                           ` Po Lu
@ 2022-01-26 11:11                             ` Robert Pluim
  2022-01-26 18:34                             ` Håkon Flatval
  1 sibling, 0 replies; 47+ messages in thread
From: Robert Pluim @ 2022-01-26 11:11 UTC (permalink / raw)
  To: Po Lu; +Cc: Håkon Flatval, emacs-devel@gnu.org

>>>>> On Wed, 26 Jan 2022 09:05:37 +0800, Po Lu <luangruo@yahoo.com> said:

    Po> Håkon Flatval <hkon20@hotmail.com> writes:
    >>> BTW, this parameter should be set during frame creation
    >> 
    >> I have put `gui_default_parameter` calls in the relevant *fns-files.
    >> I ended up putting it in wherever the 'alpha' frame parameter is set.

    Po> [...]

    >> I've added it with a very brief description. I noticed that the alpha
    >> frame parameter is not mentioned there, although it is also accessible
    >> through an X resource. I took the liberty to add it there, also with a
    >> very brief explanation. Do tell if it should be left for another commit.

    Po> That looks good to me now, but I'd like to know why the Lucid build
    Po> crashes with a 32-bit visual.  After that, and if Robert is happy, I'll
    Po> install it on master and implement the support for non-Cairo builds.

I think all the comments I had were minor formatting issues, so fine
by me.

Robert
-- 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-25 19:37                           ` Robert Pluim
@ 2022-01-26 18:16                             ` Håkon Flatval
  0 siblings, 0 replies; 47+ messages in thread
From: Håkon Flatval @ 2022-01-26 18:16 UTC (permalink / raw)
  To: Robert Pluim; +Cc: Po Lu, emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 293 bytes --]


> You mean link from the Emacs user manual to the lispref? Something
> like this will work:
>
> (@pxref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual})

I have added the links in this patch. I also updated the changelog with the
improvements you suggested.

- Håkon


[-- Attachment #2: alpha-background-changelog --]
[-- Type: application/octet-stream, Size: 1679 bytes --]

2022-01-25  Håkon Flatval  <hkon20@hotmail.com>

	* src/xterm.c (x_set_cr_source_with_gc_background):
        Add support for transparent drawing.
        (x_clear_rectangle):
        New function for drawing with background colors.
	(x_draw_rectangle):
        Use x_clear_rectangle function for drawing background.


	* src/xfns.c (Fx_create_frame, x_create_tip_frame):
	Add alpha-background defaults.
	(x_frame_parm_handlers): Add alpha-background handler.

	* src/w32fns.c (Fx_create_frame, w32_create_tip_frame):
	Add alpha-background defaults.
	(w32_frame_parm_handlers): Add alpha-background handler.

	* src/pgtkfns.c (pgtk_frame_parm_handlers):
        Add alpha-background handler.
	(Fx_create_frame, x_create_tip_frame): Add alpha-background defaults.

	* src/nsfns.m (ns_frame_parm_handlers): Add alpha-background handler.
	(Fx_create_frame): Add alpha-background defaults.

	* src/haikufns.c (haiku_create_frame, haiku_create_tip_frame):
	Add alpha-background defaults.
        (haiku_frame_parm_handlers): Add alpha-background handler.


	* src/gtkutil.c (xg_create_frame_widgets):
        Prevent GTK from filling in background.
	(xg_create_frame_widgets): Add support for 32-bit visual.


	* src/frame.h (GCALIGNED_STRUCT): Add alpha_background field.


	* src/frame.c (frame_parms): Add alpha-background frame parameter.
	(gui_set_alpha_background):
        Add gui function for setting alpha-background.
	(syms_of_frame): Add symbol for alpha-background.

	* doc/lispref/frames.texi (Font and Color Parameters):
        Add documentation on alpha-background.

	* doc/emacs/xresources.texi (Table of Resources):
	List alpha and alpha-background as X resources.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: gdk-cairo-background-transparency-009.patch --]
[-- Type: text/x-patch, Size: 16187 bytes --]

diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index ccf7e35eee..bb362ca3ea 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -149,6 +149,15 @@ Table of Resources
 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}).
 
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 2eeb8b7ed7..16748ac922 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2433,6 +2433,16 @@ Font and Color Parameters
 
 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
diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 98907bf022..8b8123c807 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..0e0cffea72 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -830,6 +830,8 @@ #define ASSIGN_CURSOR(cursor, be_cursor) \
 			 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 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..467e56ece4 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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);
 
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..5980b31d6e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
@@ -1667,6 +1668,8 @@ #define INSTALL_CURSOR(FIELD, NAME) \
 			 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)))
diff --git a/src/w32fns.c b/src/w32fns.c
index 1ea685d194..009855602e 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -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 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index faab1b1158..dea21ed142 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4598,6 +4598,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          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.screen = XScreenNumberOfScreen (screen);
+
+#if defined (USE_GTK) && defined (USE_CAIRO)
+      /* 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) && defined (USE_CAIRO) */
+
+      /* 32-bit visual not available, fallback to default visual */
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
-      vinfo_template.screen = XScreenNumberOfScreen (screen);
       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 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 1684048ea4..541fc0abaf 100644
--- a/src/xterm.c
+++ b/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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-26  1:05                           ` Po Lu
  2022-01-26 11:11                             ` Robert Pluim
@ 2022-01-26 18:34                             ` Håkon Flatval
  2022-01-27  1:00                               ` Po Lu
  1 sibling, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-26 18:34 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel@gnu.org


I have tested building without Cairo after rebasing to the latest
master. It works well now, I can't see any artifacts.

I had less luck with the LUCID build, though. Running with
`./src/emacs -q -xrm 'Emacs.synchronous: true'` opens Emacs which
immediately freezes completely with a blank screen. I have waited
for several minutes with no reaction. Running the same command with
a normal GTK build worksfine.

I'm not sure how to address this. Unless you have ideas on how to
investigate this further, I propose keeping the preprocessor `#if`
clause to avoid 32-bit visuals for non-GTK builds.

- Håkon



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-26 18:34                             ` Håkon Flatval
@ 2022-01-27  1:00                               ` Po Lu
  2022-01-29  0:01                                 ` Håkon Flatval
  0 siblings, 1 reply; 47+ messages in thread
From: Po Lu @ 2022-01-27  1:00 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I have tested building without Cairo after rebasing to the latest
> master. It works well now, I can't see any artifacts.
>
> I had less luck with the LUCID build, though. Running with
> `./src/emacs -q -xrm 'Emacs.synchronous: true'` opens Emacs which
> immediately freezes completely with a blank screen. I have waited
> for several minutes with no reaction. Running the same command with
> a normal GTK build worksfine.
>
> I'm not sure how to address this.

Well, it's not a prerequisite to installing your change, but could you
please attach to that frozen Emacs process with gdb and print a
backtrace?

Thanks.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-27  1:00                               ` Po Lu
@ 2022-01-29  0:01                                 ` Håkon Flatval
  2022-01-29  1:08                                   ` Po Lu
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-29  0:01 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 390 bytes --]


> Well, it's not a prerequisite to installing your change, but could you
> please attach to that frozen Emacs process with gdb and print a
> backtrace?

I have attached the backtrace I got from attaching with gdb to the
frozen process. I also removed the `defined (USE_CAIRO)` part from
the preprocessor statement, so that cairo builds can now have 32-
bit visuals.

- Håkon


[-- Attachment #2: bt2 --]
[-- Type: application/octet-stream, Size: 6206 bytes --]

#0  0x00007fec29d680da in __futex_abstimed_wait_common64 () at /lib64/libpthread.so.0
#1  0x00007fec29d61c20 in pthread_cond_wait@@GLIBC_2.3.2 () at /lib64/libpthread.so.0
#2  0x00007fec2b4ea3b3 in _XReply () at /usr/lib64/libX11.so.6
#3  0x00007fec2b4e5bbb in XSync () at /usr/lib64/libX11.so.6
#4  0x00007fec2b4e5c5b in _XSyncFunction () at /usr/lib64/libX11.so.6
#5  0x00007fec2b5f62cb in XdbeDeallocateBackBufferName () at /usr/lib64/libXext.so.6
#6  0x0000556e68b90a8b in tear_down_x_back_buffer (f=0x556e69f8daa0) at xfns.c:3338
#7  0x0000556e68b84601 in x_free_frame_resources (f=0x556e69f8daa0) at xterm.c:14494
#8  0x0000556e68b84fb1 in x_destroy_window (f=0x556e69f8daa0) at xterm.c:14651
#9  0x0000556e68a5a714 in delete_frame (frame=0x556e69f8daa5, force=0xb700) at frame.c:2207
#10 0x0000556e68b80a64 in x_connection_closed
    (dpy=0x556e69e21ab0, error_message=0x7ffc70c96110 "X protocol error: BadMatch (invalid parameter attributes) on protocol request 70", ioerror=false) at xterm.c:12549
#11 0x0000556e68b80cb0 in x_error_quitter (display=0x556e69e21ab0, event=0x7ffc70c962c0)
    at xterm.c:12652
#12 0x0000556e68b80bfb in x_error_handler (display=0x556e69e21ab0, event=0x7ffc70c962c0)
    at xterm.c:12625
#13 0x00007fec2b4ec5f4 in _XError () at /usr/lib64/libX11.so.6
#14 0x00007fec2b4e9337 in handle_error () at /usr/lib64/libX11.so.6
#15 0x00007fec2b4e93d5 in handle_response () at /usr/lib64/libX11.so.6
#16 0x00007fec2b4ea3cd in _XReply () at /usr/lib64/libX11.so.6
#17 0x00007fec2b4e5bbb in XSync () at /usr/lib64/libX11.so.6
#18 0x00007fec2b4e5c5b in _XSyncFunction () at /usr/lib64/libX11.so.6
#19 0x00007fec2b4cb05a in XFillRectangle () at /usr/lib64/libX11.so.6
#20 0x0000556e68d6d8c8 in display_menu
    (mw=0x556e6a058350, level=0, just_compute_p=0 '\000', highlighted_pos=0x0, hit=0x0, hit_return=0x0) at xlwmenu.c:1207
#21 0x0000556e68d7063a in XlwMenuRedisplay (w=0x556e6a058350, ev=0x0, region=0x0)
    at xlwmenu.c:2085
#22 0x0000556e68d7065f in xlwmenu_redisplay (w=0x556e6a058350) at xlwmenu.c:2095
#23 0x0000556e68b7c5ca in handle_one_xevent
    (dpyinfo=0x556e69e321e0, event=0x7ffc70c96e50, finish=0x7ffc70c96e40, hold_quit=0x7ffc70c96f70) at xterm.c:9173
#24 0x0000556e68b7f2ad in XTread_socket (terminal=0x556e69df9cf0, hold_quit=0x7ffc70c96f70)
    at xterm.c:11843
#25 0x0000556e68bc7ec0 in gobble_input () at keyboard.c:7113
#26 0x0000556e68bc83b2 in handle_async_input () at keyboard.c:7344
#27 0x0000556e68bc83d1 in process_pending_signals () at keyboard.c:7358
#28 0x0000556e68bc8411 in unblock_input_to (level=0) at keyboard.c:7373
#29 0x0000556e68bc8446 in totally_unblock_input () at keyboard.c:7401
#30 0x0000556e68b831f2 in x_wait_for_event (f=0x556e69f8daa0, eventtype=19) at xterm.c:13793
#31 0x0000556e68b84186 in x_make_frame_visible (f=0x556e69f8daa0) at xterm.c:14276
#32 0x0000556e68b8436c in x_make_frame_visible_invisible (f=0x556e69f8daa0, visible=true)
    at xterm.c:14344
#33 0x0000556e68a5b767 in Fmake_frame_visible (frame=0x556e69f8daa5) at frame.c:2731
#34 0x0000556e68c825d3 in funcall_subr
    (subr=0x556e69145f00 <Smake_frame_visible>, numargs=1, args=0x7ffc70c972f8)
    at eval.c:3137
#35 0x0000556e68cd4eab in exec_byte_code
    (bytestr=0x7fec26b83ff4, vector=0x7fec26b82fb5, maxdepth=0x2e, args_template=256, nargs=1, args=0x7ffc70c977c8) at bytecode.c:676
#36 0x0000556e68cd4e54 in exec_byte_code
    (bytestr=0x7fec26b840b4, vector=0x7fec26b82f35, maxdepth=0xe, args_template=257, nargs=1, args=0x7ffc70c97ef8) at bytecode.c:671
#37 0x0000556e68c828af in fetch_and_exec_byte_code
    (fun=0x7fec26b82ee5, args_template=257, nargs=1, args=0x7ffc70c97ef0) at eval.c:3187
#38 0x0000556e68c82c72 in funcall_lambda
    (fun=0x7fec26b82ee5, nargs=1, arg_vector=0x7ffc70c97ef0) at eval.c:3268
#39 0x0000556e68c820ba in funcall_general
    (fun=0x7fec26b82ee5, numargs=1, args=0x7ffc70c97ef0) at eval.c:3035
#40 0x0000556e68c82316 in Ffuncall (nargs=2, args=0x7ffc70c97ee8) at eval.c:3085
#41 0x0000556e68c80fed in Fapply (nargs=2, args=0x7ffc70c97ee8) at eval.c:2649
#42 0x0000556e68c824de in funcall_subr
    (subr=0x556e69154100 <Sapply>, numargs=2, args=0x7ffc70c97ee8) at eval.c:3117
#43 0x0000556e68cd4eab in exec_byte_code
    (bytestr=0x7fec267f73e4, vector=0x7fec267f7405, maxdepth=0x3a, args_template=128, nargs=1, args=0x7ffc70c98420) at bytecode.c:676
#44 0x0000556e68cd4e54 in exec_byte_code
    (bytestr=0x7fec26a4cd9c, vector=0x7fec268454d5, maxdepth=0x3a, args_template=256, nargs=1, args=0x7ffc70c98900) at bytecode.c:671
#45 0x0000556e68cd4e54 in exec_byte_code
    (bytestr=0x7fec269c00fc, vector=0x7fec269bfe35, maxdepth=0x1a, args_template=0, nargs=0, args=0x7ffc70c98dd8) at bytecode.c:671
#46 0x0000556e68cd4e54 in exec_byte_code
    (bytestr=0x7fec269c3a24, vector=0x7fec269971ad, maxdepth=0x3a, args_template=0, nargs=0, args=0x7ffc70c992e0) at bytecode.c:671
#47 0x0000556e68cd4e54 in exec_byte_code
    (bytestr=0x7fec269c5d7c, vector=0x7fec26996975, maxdepth=0x26, args_template=0, nargs=0, args=0x7ffc70c99870) at bytecode.c:671
#48 0x0000556e68c828af in fetch_and_exec_byte_code
    (fun=0x7fec26996935, args_template=0, nargs=0, args=0x7ffc70c99870) at eval.c:3187
#49 0x0000556e68c82c72 in funcall_lambda
    (fun=0x7fec26996935, nargs=0, arg_vector=0x7ffc70c99870) at eval.c:3268
#50 0x0000556e68c82a68 in apply_lambda (fun=0x7fec26996935, args=0x0, count=4) at eval.c:3212
#51 0x0000556e68c80b3e in eval_sub (form=0x7fec26ea7233) at eval.c:2571
#52 0x0000556e68c7ff2b in Feval (form=0x7fec26ea7233, lexical=0x0) at eval.c:2349
#53 0x0000556e68bb974f in top_level_2 () at keyboard.c:1146
#54 0x0000556e68c7e0e5 in internal_condition_case
    (bfun=0x556e68bb972c <top_level_2>, handlers=0x90, hfun=0x556e68bb904b <cmd_error>)
    at eval.c:1485
#55 0x0000556e68bb97a0 in top_level_1 (ignore=0x0) at keyboard.c:1154
#56 0x0000556e68c7d78c in internal_catch
    (tag=0xef70, func=0x556e68bb9751 <top_level_1>, arg=0x0) at eval.c:1216
#57 0x0000556e68bb9677 in command_loop () at keyboard.c:1114
#58 0x0000556e68bb8bed in recursive_edit_1 () at keyboard.c:724
#59 0x0000556e68bb8d99 in Frecursive_edit () at keyboard.c:807
#60 0x0000556e68bb5220 in main (argc=4, argv=0x7ffc70c99de8) at emacs.c:2427

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: gdk-cairo-background-transparency-010.patch --]
[-- Type: text/x-patch, Size: 16141 bytes --]

diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index ccf7e35eee..bb362ca3ea 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -149,6 +149,15 @@ Table of Resources
 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}).
 
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 2eeb8b7ed7..16748ac922 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2433,6 +2433,16 @@ Font and Color Parameters
 
 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
diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 98907bf022..8b8123c807 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..0e0cffea72 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -830,6 +830,8 @@ #define ASSIGN_CURSOR(cursor, be_cursor) \
 			 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 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..467e56ece4 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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);
 
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..5980b31d6e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
@@ -1667,6 +1668,8 @@ #define INSTALL_CURSOR(FIELD, NAME) \
 			 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)))
diff --git a/src/w32fns.c b/src/w32fns.c
index 1ea685d194..009855602e 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -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 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index faab1b1158..2f2e33fa69 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4598,6 +4598,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          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.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_template.screen = XScreenNumberOfScreen (screen);
       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 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 3f277c5b87..ab5fd46c4c 100644
--- a/src/xterm.c
+++ b/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);
 }
 
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Sv: Support for background transparency
  2022-01-29  0:01                                 ` Håkon Flatval
@ 2022-01-29  1:08                                   ` Po Lu
  0 siblings, 0 replies; 47+ messages in thread
From: Po Lu @ 2022-01-29  1:08 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> I have attached the backtrace I got from attaching with gdb to the
> frozen process. I also removed the `defined (USE_CAIRO)` part from
> the preprocessor statement, so that cairo builds can now have 32-
                                     ^

Did you forget a word here?  Anyway, I'm happy now, so if nobody has
anything further to say I'll install this.

Thanks for your work on Emacs.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-25 19:31                       ` Robert Pluim
@ 2022-01-29 10:26                         ` Po Lu
  2022-01-29 15:17                           ` Håkon Flatval
  0 siblings, 1 reply; 47+ messages in thread
From: Po Lu @ 2022-01-29 10:26 UTC (permalink / raw)
  To: Robert Pluim; +Cc: Håkon Flatval, emacs-devel@gnu.org

Robert Pluim <rpluim@gmail.com> writes:

> When making the same entry for multiple functions in the same file,
> you can combine them:
>
> * src/xfns.c (Fx_create_frame, x_create_tip_frame): Add
> alpha-background defaults.
> (x_frame_parm_handlers): Add alpha-background handler.
>
> Robert

Hakon, do you have a good commit message somewhere?  Or should I use the
one you sent in your earlier follow-up to Robert?  (I was about to
install your change, but then `git am' complained about there not being
a commit message.)

Thanks.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-29 10:26                         ` Po Lu
@ 2022-01-29 15:17                           ` Håkon Flatval
  2022-01-30  0:53                             ` Po Lu
  0 siblings, 1 reply; 47+ messages in thread
From: Håkon Flatval @ 2022-01-29 15:17 UTC (permalink / raw)
  To: Po Lu; +Cc: Robert Pluim, emacs-devel@gnu.org

[-- Attachment #1: Type: text/plain, Size: 274 bytes --]


> Hakon, do you have a good commit message somewhere?

Yes, sorry - I should have created the last patch with `format-patch`
instead of just a normal `diff`. I have included a formatted patch
now.

Thanks for all your feedback throughout this effort.

- Håkon


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-background-transparency-support-for-GTK-Cairo.patch --]
[-- Type: text/x-patch, Size: 16941 bytes --]

From e9f4a8b111e31b73873e56beaf43a3dcab1c72b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?H=C3=A5kon=20Flatval?= <hkon20@hotmail.com>
Date: Sat, 29 Jan 2022 16:13:06 +0100
Subject: [PATCH] Add background transparency support for GTK+Cairo

---
 doc/emacs/xresources.texi |  9 +++++++
 doc/lispref/frames.texi   | 10 ++++++++
 src/frame.c               | 29 +++++++++++++++++++++
 src/frame.h               |  4 +++
 src/gtkutil.c             | 14 ++++++++++-
 src/haikufns.c            |  7 +++++-
 src/nsfns.m               |  3 +++
 src/pgtkfns.c             |  5 ++++
 src/w32fns.c              |  8 ++++++
 src/xfns.c                | 28 +++++++++++++++++++--
 src/xterm.c               | 53 +++++++++++++++++++++++++++++++--------
 11 files changed, 156 insertions(+), 14 deletions(-)

diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index ccf7e35eee..bb362ca3ea 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -149,6 +149,15 @@ Table of Resources
 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}).
 
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 7d3ce9d74e..f8188708e5 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2433,6 +2433,16 @@ Font and Color Parameters
 
 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
diff --git a/src/frame.c b/src/frame.c
index 8aaff949ba..c331cff32b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3907,6 +3907,7 @@ DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
   {"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");
diff --git a/src/frame.h b/src/frame.h
index cb2f58e261..5d5f2122fb 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -637,6 +637,9 @@ #define EMACS_FRAME_H
      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 @@ #define EMACS_CLASS "Emacs"
 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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 98907bf022..8b8123c807 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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),
diff --git a/src/haikufns.c b/src/haikufns.c
index 58a2e1d464..0e0cffea72 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -830,6 +830,8 @@ #define ASSIGN_CURSOR(cursor, be_cursor) \
 			 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 @@ DEFUN ("haiku-frame-restack", Fhaiku_frame_restack, Shaiku_frame_restack, 2, 3,
     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
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a..467e56ece4 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -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);
 
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9c37c04810..5980b31d6e 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1043,6 +1043,7 @@ frames (each of which corresponds to one page).  Each frame should be
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 
@@ -1667,6 +1668,8 @@ #define INSTALL_CURSOR(FIELD, NAME) \
 			 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)))
diff --git a/src/w32fns.c b/src/w32fns.c
index 1ea685d194..009855602e 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -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 @@ w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
   w32_set_z_group,
   0, /* x_set_override_redirect */
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xfns.c b/src/xfns.c
index faab1b1158..2f2e33fa69 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4598,6 +4598,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
                          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.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_template.screen = XScreenNumberOfScreen (screen);
       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 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
   x_set_z_group,
   x_set_override_redirect,
   gui_set_no_special_glyphs,
+  gui_set_alpha_background,
 };
 
 void
diff --git a/src/xterm.c b/src/xterm.c
index 3f277c5b87..ab5fd46c4c 100644
--- a/src/xterm.c
+++ b/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);
 }
 
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: Sv: Sv: Support for background transparency
  2022-01-29 15:17                           ` Håkon Flatval
@ 2022-01-30  0:53                             ` Po Lu
  0 siblings, 0 replies; 47+ messages in thread
From: Po Lu @ 2022-01-30  0:53 UTC (permalink / raw)
  To: Håkon Flatval; +Cc: Robert Pluim, emacs-devel@gnu.org

Håkon Flatval <hkon20@hotmail.com> writes:

> Yes, sorry - I should have created the last patch with `format-patch`
> instead of just a normal `diff`. I have included a formatted patch
> now.

Installed, thanks.



^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2022-01-30  0:53 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-04 19:45 Support for background transparency Håkon Flatval
2021-11-04 20:06 ` Eli Zaretskii
2021-11-04 20:17 ` Lars Ingebrigtsen
2021-11-27 23:01   ` Håkon Flatval
2021-11-28  0:35     ` Sv: " arthur miller
2021-11-28 13:32       ` Lars Ingebrigtsen
2021-11-28 16:04         ` Arthur Miller
2021-11-28 20:33           ` Håkon Flatval
2021-11-29  2:56             ` Arthur Miller
2021-11-28  7:41     ` Eli Zaretskii
2021-11-28  7:47       ` Po Lu
2021-11-28  8:27         ` Eli Zaretskii
2021-12-01 18:54       ` Sv: " Håkon Flatval
2021-12-09 17:13         ` Håkon Flatval
2021-12-10  0:40           ` Lars Ingebrigtsen
2022-01-19 17:26             ` Sv: " Håkon Flatval
2022-01-20  0:52               ` Po Lu
2022-01-20 19:52                 ` Sv: " Håkon Flatval
2022-01-21  0:59                   ` Po Lu
2022-01-23 13:48                     ` Håkon Flatval
2022-01-24  0:11                       ` Po Lu
2022-01-25 17:53                         ` Håkon Flatval
2022-01-26  1:00                           ` Po Lu
2022-01-24 10:22                       ` Po Lu
2022-01-25 19:47                         ` Håkon Flatval
2022-01-25 19:37                           ` Robert Pluim
2022-01-26 18:16                             ` Håkon Flatval
2022-01-26  1:05                           ` Po Lu
2022-01-26 11:11                             ` Robert Pluim
2022-01-26 18:34                             ` Håkon Flatval
2022-01-27  1:00                               ` Po Lu
2022-01-29  0:01                                 ` Håkon Flatval
2022-01-29  1:08                                   ` Po Lu
2022-01-20  9:12               ` Robert Pluim
2022-01-23 21:43                 ` Håkon Flatval
2022-01-24  9:14                   ` Robert Pluim
2022-01-25 20:00                     ` Håkon Flatval
2022-01-25 19:31                       ` Robert Pluim
2022-01-29 10:26                         ` Po Lu
2022-01-29 15:17                           ` Håkon Flatval
2022-01-30  0:53                             ` Po Lu
2021-11-28 13:41     ` Lars Ingebrigtsen
2021-11-28 15:05       ` Sv: " Håkon Flatval
2021-11-28 16:07         ` Gregor Zattler
2021-11-28 16:32         ` Lars Ingebrigtsen
2021-11-28 18:10     ` Jean Louis
2021-11-28 18:44       ` Sv: " Håkon Flatval

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).