compton icon indicating copy to clipboard operation
compton copied to clipboard

Maintaining 100% Opacity of the Content in a Transparent Menu (w/ example)

Open quadpixels opened this issue 10 years ago • 4 comments

Hello Compton, I love Compton so much, especially the gorgeous blur effects acted upon transparent menus/windows! I think there is a little improvement that can be made to the Transparent Menus. (I don't know if this already exists in a fork or not, so if there is one please delete this issue) When a menu is made transparent, all of its pixels are made transparent, regardless of whether a pixel is content or background. This means when you set the menu opacity to a very low value, you may not be able to easily see the text and icons on the menu. (See the picture)

example

I think a simple way to make the contents opaque is through the usage of the custom shader (The one used in the --glx-fshader-win flag.) If we only make the background menu colors transparent, we can obtain the effects in the second picture. The custom shader looks like the following:

uniform float opacity;
uniform bool invert_color;
uniform sampler2D tex;
void main() {
  vec4 c = texture2D(tex, gl_TexCoord[0]);
  float eps = 0.018f;
  float eps1 = 0.0f;
  if (invert_color)
     c = vec4(vec3(c.a, c.a, c.a) - vec3(c), c.a);
  if(
  (c.r > 0.807843+eps1-eps && c.r < 0.807843+eps1+eps &&
   c.g > 0.807843+eps1-eps && c.g < 0.807843+eps1+eps &&
   c.b > 0.807843+eps1-eps && c.b < 0.807843+eps1+eps) ||
  (c.r > 0.953255+eps1-eps && c.r < 0.953255+eps1+eps &&
   c.g > 0.953255+eps1-eps && c.g < 0.953255+eps1+eps &&
   c.b > 0.953255+eps1-eps && c.b < 0.953255+eps1+eps)
  ) { c *= opacity; } 
  else {  }
  gl_FragColor = c;
}

The color values (0.953255, 0.953255, 0.953255) (0xFCFCFC) and (0.807843, 0.807843, 0.807843) (0xCECECE) are the "menu background color" and "normal background color" (used in Whisker Menu) of the XFCE GreyBird GTK3 theme. The eps value is determined using personal experience and may need more reasoning.

However, there is a catch in using colors: it stops working when the background of menu is not a solid color. I could be wrong, but I assume there is not an easy way to differentiate the background and the foreground as the information is lost when the content of the menu is handed to Compton in the form of a bitmap? Anyway the "color hack" seems to work well for me as of now.

This involved changing 3 files; the following is not elegant and it adds a dependency (GTK3) , but it demonstrates the idea. I added a flag called --tommy-flag, and you can run compton with this new flag to see the results.

Hope this may be useful and thanks so much! quadpixels (p.s. I'm not sure if this is the correct place to post this, so you may remove this issue if I'm wrong)

-----------------------Appendix--------------------------

diff compton-my/src/common.h gitrepo/compton/src/common.h 
579,581d578
< 
<   bool tommy_flag;  // Grab BG color from GTK settings and use them on the custom shader
< 
diff compton-my/src/compton.c gitrepo/compton/src/compton.c
14,17d13
< // Hack: Automatically fetch the normal background and menu background colors
< #include <gtk-3.0/gtk/gtk.h>
< #include <gtk-3.0/gdk/gdk.h>
< 
5755d5750
<   { "tommy-flag", no_argument, NULL, 321 },
6026,6085d6020
<     case 321: {
<         ps->o.tommy_flag = true;
<       gtk_init(NULL, NULL);
<       GdkRGBA bg_color_win, bg_color_menu;
<       GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
<       GtkStyleContext* ctxt = gtk_widget_get_style_context(win);
<       gtk_style_context_get_background_color(ctxt, GTK_STATE_FLAG_NORMAL, &bg_color_win);
<       gtk_widget_destroy(win);
<       GtkWidget* menu = gtk_menu_new();
<       ctxt = gtk_widget_get_style_context(menu);
<       gtk_style_context_get_background_color(ctxt, GTK_STATE_FLAG_NORMAL, &bg_color_menu);
<       gtk_widget_destroy(menu);
<       printf("I have got some colors from GTK! (%g,%g,%g) and (%g,%g,%g)\n",
<           bg_color_win.red, bg_color_win.green, bg_color_win.blue,
<           bg_color_menu.red,bg_color_menu.green,bg_color_menu.blue);
<       const int N = 2;
<       double x[2][3] = { { 0.807, 0.807, 0.807 }, { 0.953, 0.953, 0.953 } };
<       x[0][0] = bg_color_win.red; x[0][1] = bg_color_win.green; x[0][2] = bg_color_win.blue;
<       x[1][0] = bg_color_menu.red;x[1][1] = bg_color_menu.green;x[1][2] = bg_color_menu.blue;
<       const char* part1 = 
<           "uniform float opacity;\n"
<           "uniform bool invert_color;\n"
<           "uniform sampler2D tex;\n"
<           "void main() {\n"
<           "  vec4 c = texture2D(tex, gl_TexCoord[0]);\n"
<           "  float eps = 0.018f;\n"
<           "  float eps1 = 0.0f;\n"
<           "  if (invert_color)\n"
<           "    c = vec4(vec3(c.a, c.a, c.a) - vec3(c), c.a);\n"
<           "  if(";
< 
<       char tmp[200], conditions[2000];
<       int offset = 0;
<       for(int n=0; n<N; n++) {
<           double red = x[n][0], green = x[n][1], blue = x[n][2];
<           sprintf(tmp, "  (c.r > %g+eps1-eps && c.r < %g+eps1+eps &&\n"
<               "   c.g > %g+eps1-eps && c.g < %g+eps1+eps &&\n"
<               "   c.b > %g+eps1-eps && c.b < %g+eps1+eps)",
<               red, red, green, green, blue, blue);
<           if (n < N-1) {
<               unsigned l = strlen(tmp);
<               sprintf(tmp+l, " ||\n");
<           }
<           
<           sprintf(conditions + offset, "%s", tmp);
<           offset += strlen(tmp);
<       }
< 
<       const char* part2 = 
<           "  ) { c *= opacity; } \n"
<           "  else {  }\n"
<           "  gl_FragColor = c;\n"
<           "}\n";
< 
<       char* big = (char*)malloc(10000);
<       sprintf(big, "%s\n%s\n%s", part1, conditions, part2);
<       ps->o.glx_fshader_win_str = mstrcpy(big);
<       free(big);
<       break;
<     }
diff compton-my/Makefile gitrepo/compton/Makefile 
12,13c12,13
< LIBS = -lm -lrt $(shell pkg-config --libs gtk+-3.0)
< INCS = $(shell pkg-config --cflags gtk+-3.0)

---
> LIBS = -lm -lrt
> INCS =

quadpixels avatar May 13 '15 17:05 quadpixels

how it will work with a gradiented background?

actionless avatar May 14 '15 06:05 actionless

If you ask "how to make it work with gradiented background", the conditions in the shader need to be made to match all the colors in the gradient. It's like determining whether a point is on a line segment...

quadpixels avatar May 14 '15 15:05 quadpixels

@quadpixels That sounds very useful!

Could you create a pull request (from a separate branch in your fork) for this? This makes it easier to discuss/review/test the code.

blueyed avatar Jul 08 '15 15:07 blueyed

@blueyed Thanks for the advice! It does look better to use the pull request feature than posting an issue. I just created pull request #295 . The code should compile, although it is not of "production-ready" level quality. I think getting this feature done perfectly is beyond my knowledge right now, so I am also looking forward to learning from discussions/reviews//tests.

quadpixels avatar Jul 15 '15 03:07 quadpixels