views:

20

answers:

1

Hi, I am in the process of adding drag and drop support to an existing Mono/C#/GTK# application. I was wondering whether it was possible to use RGBA transparency on the icons that appear under the mouse pointer when I start dragging an object.

So far, I realized the following:

  • I can set the bitmap in question by calling the Gtk.Drag.SourceSetIconPixbuf() method. However, no luck with alpha transparency: pixels that are not fully opaque would get 100% transparent this way.
  • I also tried calling RenderPixmapAndMask() on the GdkPixbuf so that I could use Gtk.Drag.SourceSetIcon() with an RGBA colormap of my Screen. It didn't work either: whenever I started dragging, I got the following error:

    [Gdk] IA__gdk_window_set_back_pixmap: assertion 'pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap)' failed.

    This way, the pixmap doesn't even get copied, only a white shape (presumably set by the mask argument of SetSourceIcon()) shows up on dragging.

I'd like to ask if there's a way to make these icons have alpha transparency, despite the fact that I failed to do so. In case it's impossible, answers discussing the reasons of the lack of this feature would also be helpful. Thank you.

(Compositing is - of course - enabled on my desktop (Ubuntu/10.10, Compiz/0.8.6-0ubuntu9).)

A: 

Ok, finally I solved it. You should create a new Gtk.Window of POPUP type, set its Colormap to your screen's RGBA colormap, have the background erased by Cairo to a transparent color, draw whatever you'd like on it and finally pass it on to Gtk.Drag.SetIconWidget().

Sample code (presumably you'll want to use this inside OnDragBegin, or at a point where you have a valid drag context to be passed to SetIconWidget()):

Gtk.Window window = new Gtk.Window (Gtk.WindowType.Popup);

window.Colormap = window.Screen.RgbaColormap;
window.AppPaintable = true;
window.Decorated = false;
window.Resize (/* specify width, height */);

/* The cairo context can only be created when the window is being drawn by the
 * window manager, so wrap drawing code into an ExposeEvent delegate. */
window.ExposeEvent += delegate {

    Context ctx = Gdk.CairoHelper.Create (window.GdkWindow);

    /* Erase the background */
    ctx.SetSourceRGBA (0, 0, 0, 0);
    ctx.Operator = Operator.Source;
    ctx.Paint ();

    /* Draw whatever you'd like to here, and then clean up by calling
       Dispose() on the context's target. */

    (ctx.Target as IDisposable).Dispose ();
};

Gtk.Drag.SetIconWidget(drag_context, window, 10, 10);
brncsk