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 theGdkPixbuf
so that I could useGtk.Drag.SourceSetIcon()
with an RGBA colormap of myScreen
. 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 ofSetSourceIcon()
) 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).)
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);
精彩评论