LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   gtk window transparency (https://www.linuxquestions.org/questions/programming-9/gtk-window-transparency-660677/)

PatrickNew 08-05-2008 02:18 PM

gtk window transparency
 
I'm getting a bit confused with this. The goal is to create a window so that when you pack things into it, the window itself is translucent, but the widgets in the window are not (unless that thing is an image with an alpha channel). I'm writing in gtkmm, but if anyone knows the answer in any other port of gtk, I can translate that back.

I thought Gtk::Window::set_opacity() was supposed to do this, but on my machine it does absolutely nothing (and yes, I'm running a compositing manager. I've got awn and screenlets running while I test, so I know it works) Gdk::Display::supports_composite() is returning true on the display.

I found some other techniques that involved drawing on the windows Gdk::Window, but I think that those were pseudo-transparency hacks. I want to work with compositing.

rocket357 08-05-2008 03:26 PM

What value are you passing in to set_opacity()? Stupid question, I know, but I thought I'd ask =D

ne pas 08-05-2008 04:30 PM

Is your compositing manager running?

Following snippet works for me after I set "Visual Effects" to "Normal" or "Extra" in the appearance preferences ("System" -> "Preferences" -> "Appearance" -> "Visual Effects") [Ubuntu].
Code:

#include <gtk/gtk.h>

gint main(gint argc, gchar **argv)
{
  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_window_set_opacity(GTK_WINDOW(window), 0.3);

  gtk_widget_show_all(window);

  gtk_main();
}


PatrickNew 08-05-2008 06:25 PM

@rocket357: I've tried 0, 1, and .5. No difference between them.

@ne_pas: The compositing manager is running. A 'ps -A' shows xcompmgr and both awn and screenlets are running with transparency. So this means that gtk_window_set_opacity should work, it's just not on my machine? I'll give it another shot and reply.

PatrickNew 08-05-2008 06:36 PM

Interesting. Your example code runs, but still gives me an opaque window. Just to clarify, I'm using openbox and xcompmgr. Hrm, I'll try again in Gnome and report back.

PatrickNew 08-05-2008 06:43 PM

Well, the exact same code behaves as expected on Metacity with compositing or on Compiz. I guess that probably makes this an xcompmgr bug.

PatrickNew 08-05-2008 08:44 PM

Hrm, well perhaps set_opacity isn't what I want. set_opacity() is also controlling the opacity of the widgets. For example, I create a transparent window, then pack a GtkLabel into it - the Label gets transparent with the window. Is there some other way of doing this?

Su-Shee 08-06-2008 06:41 AM

That's not a real bug of xcompmgr - xcompmgr is just rather old and was only meant to be a small design study to show that compositing works.

The difference is as far as I know that xcompmgr does not use the GLX_blahbla_whatever_pixmap thingie function Open GL compositing stuff as Compiz, metacity and Xfce uses. (Didn't exist at the time, xcompmgr seems to speak more directly with the graphic's layer...)

The appropriate test from within Gtk wether or not transparency / compositing is supported seems to depend exactly on this - that's why for example _some_ (not all) Cairo-based transparent gadgets like cairo clock or screenlets do not work.

And: If you need per-widget transparency within a Gtk app, you'll need an engine actually supporting this. There is none right now but the most recent SVN/CVS stuff of "murrine", the fancy Cairo-based Gtk-engine.

And I maybe totally wrong - it's really no fun to google in-depth information about all the transparency compositing gui widget foobar.

So, in short: Just use a more contemporary compositing manager. There's also a cairo-based one, but it depends on some Gnome stuff.

Addition: The combination of metisse and nucleo doesn't work either with most Gtk-stuff - the compositing mechanism is just not recognized.

swift2008 08-06-2008 08:02 AM

Quote:

Originally Posted by ne pas (Post 3237916)
Is your compositing manager running?

Following snippet works for me after I set "Visual Effects" to "Normal" or "Extra" in the appearance preferences ("System" -> "Preferences" -> "Appearance" -> "Visual Effects") [Ubuntu].
Code:

#include <gtk/gtk.h>

gint main(gint argc, gchar **argv)
{
  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_window_set_opacity(GTK_WINDOW(window), 0.3);

  gtk_widget_show_all(window);

  gtk_main();
}


hi

i am using fedora9
i run this program in my machine..
it is not working for me.

not showing any transaparency.
may i know the reasons for this.

and how can i overcome this problem

any help thanks inhand

ne pas 08-06-2008 09:25 AM

I hacked some stuff together for per-widget transparency, from various sources, it works at least with compiz and xcompmgr (never used bevor). My metacity (GNOME 2.20) has no build-in support for compositing, so although it has alpha-channel support, alpha will not be honored (see GdkScreen - gdk_screen_get_rgba_colormap).

gtk_transparent_window.c
Code:

#include <gtk/gtk.h>

static gboolean alpha_channel_support = FALSE;

static gboolean on_window_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
  cairo_t *cr;

  cr = gdk_cairo_create(widget->window); // create cairo context

  if(alpha_channel_support)
      // set source to RGB-Alpha
      cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.7);
  else
      // set source to RGB-Alpha
      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); // set color RGB

  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // set drawing compositing operator
                                                // SOURCE -> replace destination

  cairo_paint(cr); // paint source

  cairo_destroy(cr);

  return FALSE;
}

gint main(gint argc, gchar **argv)
{
  GtkWidget *window, *button, *vbox;
  GdkScreen *screen;
  GdkColormap *colormap;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL);
  g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(on_window_expose_event), NULL);

  gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

  gtk_widget_set_app_paintable(window, TRUE); // allow application to paint on widget

  screen = gtk_widget_get_screen(window);

  colormap = gdk_screen_get_rgba_colormap(screen); // get colormap with alpha channel

  if(colormap != NULL)
  {
      alpha_channel_support = TRUE;
  }
  else
  {
      alpha_channel_support = FALSE;

      colormap = gdk_screen_get_rgb_colormap(screen);

      g_message("Screen supports no alpha channels\n");
  }

  gtk_widget_set_colormap(window, colormap);

  button = gtk_button_new();
  gtk_button_set_label(GTK_BUTTON(button), "Don't Press!");

  vbox = gtk_vbox_new(TRUE, 5);
  gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5);

  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}


ne pas 08-06-2008 09:38 AM

Quote:

Originally Posted by swift2008 (Post 3238628)
not showing any transaparency.
may i know the reasons for this.

and how can i overcome this problem

You need to have a compositing manager running, like compiz, xcompmgr or metacity (has built-in compositing since GNOME v2.22).

phorgan1 09-06-2008 01:23 PM

Background image with alpha
 
Quote:

Originally Posted by ne pas (Post 3238714)
I hacked some stuff together for per-widget transparency ... stuff elided ...

Thank you. Your code worked great for me until---I wanted to try to put a background with alpha into the transparent window. The background showed up fine before I added your code, but the transparent parts weren't. Then I added your code and the background is as transparent as I want to make it, but the background image is gone. Help!!! Here's my code, (much stolen directly from you;)

Code:

#include <gtk/gtk.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <stdlib.h>

GtkWidget *window;
static gboolean alpha_channel_support = FALSE;

static gboolean
expose_window(GtkWidget *widget, GdkEventExpose *event, gpointer date)
    {
    cairo_t *cr;

    cr = gdk_cairo_create(widget->window); /* create cairo context */

    if(alpha_channel_support){
    /* set source to RGB-Alpha */
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, .6);
        g_print("got alpha in expose");
    }else{
    /* set source to RGB-Alpha */
        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); /* set color RGB */
    }

    /* set drawing compositing operator */
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    /* SOURCE -> replace destination */

    cairo_paint(cr); /* paint source */

    cairo_destroy(cr);

    return FALSE;
}

int
setupwindow()
{
    GdkPixmap *background;
    GdkPixbuf *pixbuf;
    GdkPixbuf *scaled;
    GdkScreen *screen;
    GdkColormap *colormap;
    GError *error=NULL;
    GtkStyle *style;
    gboolean boolit;

    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(expose_window),NULL);
    gtk_window_set_title(GTK_WINDOW(window), "clock");
    gtk_window_stick(GTK_WINDOW(window));
    gtk_window_set_resizable(GTK_WINDOW(window),TRUE);
    gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window),TRUE);
    gtk_window_set_keep_above(GTK_WINDOW(window),TRUE);
    gtk_container_set_border_width(GTK_CONTAINER(window), 3);
    gtk_window_set_decorated(GTK_WINDOW(window),TRUE);
    gtk_window_set_default_size(GTK_WINDOW(window),100,100);
    gtk_widget_set_app_paintable(window,TRUE);

    /* Get the screen to get the colormap */
    screen=gtk_widget_get_screen(window);
    colormap = gdk_screen_get_rgba_colormap(screen);
    if(colormap != NULL){
        alpha_channel_support=TRUE;
    } else {
        alpha_channel_support=FALSE;
        colormap=gdk_screen_get_rgb_colormap(screen);
        g_print("Sorry, no alpha!\n");
    }
    /* Tell the window to use the colormap */
    gtk_widget_set_colormap(window,colormap);

    /* Get a pixbuf from the image file */
    pixbuf=gdk_pixbuf_new_from_file("clockface.png",&error);

    if(pixbuf==NULL){
        g_print("Failed to open background image: %s\n", error->message);
        g_error_free(error);
        error=NULL;
        return 0;
    }
    /* Make it the same size as the window */
    scaled=gdk_pixbuf_scale_simple(pixbuf,100,100, GDK_INTERP_BILINEAR);
    /* Render it using the colormap of the window */
    gdk_pixbuf_render_pixmap_and_mask_for_colormap(scaled,colormap,&background,NULL,0);
    /* Make a new style, stick the background in it, tell window to use it. */
    style = gtk_style_new();
    style->bg_pixmap[0] = background;
    gtk_widget_set_style(GTK_WIDGET(window),GTK_STYLE(style));

    /*gtk_window_set_opacity(GTK_WINDOW(window),0.3);*/
    gtk_window_move(GTK_WINDOW(window), 0, 0);
    gtk_widget_show_all(window);
    return 1;
}

int
main(int argc, char **argv)
{
    gtk_init(&argc,&argv);
    if(!setupwindow()){
        exit(EXIT_FAILURE);
    }
    gtk_main();
    exit(EXIT_SUCCESS);
}

Does anyone have any idea how I can get a background image with alpha to work? What I'm trying to do eventually is to make a free floating clock with only the face showing. (Even better if it's notification area icon would dynamically keep the time when the application is not showing;) I know it can be done from X, but how do you do in in GDK/GTK?

Patrick

PatrickNew 09-08-2008 12:23 PM

I've done stuff like that before, and I found it much easier to use a shaped window instead of transparency. Look at gdk_window_shape_combine_mask, that's probably what you want.


All times are GMT -5. The time now is 08:17 PM.