 |
GTK+ Forums Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
|
|
|
| Author |
Message |
|
|
Calin Guest
|
Posted: Wed Sep 21, 2005 7:01 am Post subject: shape masked widgets on gtk 2.8.x |
|
|
Hello,
This is a question I've post on gtk-list mailing list, but I got no reply. I hope this forum will have more traffic at least.
I've been trying for some time to develop a program that can move icons on a canvas, but if the icons are shape masked it looks very ugly. The masked area of the icon is messed up. See for yourself in the following code:
X---------------------------------------
#include <gtk/gtk.h>
GtkWidget *img_slot, *fixed_evbox;
GtkWidget *fixed;
int new_x, new_y, old_x, old_y, child_x = 150, child_y = 150, orig_x, orig_y, dx = 0, dy = 0;;
gboolean dragging=FALSE;
void set_shape_mask_from_file (GtkWidget *widget, gchar *file)
{
GdkPixbuf *pix;
GdkBitmap *shape_mask;
guchar *data;
pix = gdk_pixbuf_new_from_file (file, NULL);
data = g_new0(guchar, gdk_pixbuf_get_width (pix) * gdk_pixbuf_get_height (pix));
shape_mask = gdk_bitmap_create_from_data (widget->window, data,
gdk_pixbuf_get_width (pix), gdk_pixbuf_get_height (pix), 100);
gdk_pixbuf_render_threshold_alpha (pix, shape_mask, 0, 0, 0, 0,
gdk_pixbuf_get_width (pix), gdk_pixbuf_get_height (pix), 100);
gtk_widget_shape_combine_mask (widget, shape_mask, 0, 0);
}
gboolean img_event(GtkWidget *w,
GdkEvent *ev,
gpointer data)
{
if (ev->type == GDK_BUTTON_PRESS) {
if (ev->button.button == 1) {
old_x = ev->button.x_root;
old_y = ev->button.y_root;
orig_x = ev->button.x;
orig_y = ev->button.y;
dx = dy = 0;
gtk_grab_add(img_slot);
dragging = TRUE;
return TRUE;
}
}
else if (ev->type == GDK_MOTION_NOTIFY) {
if (ev->motion.state & GDK_BUTTON1_MASK) {
if (dragging) {
new_x = ev->motion.x_root;
new_y = ev->motion.y_root;
dx += new_x-old_x;
dy += new_y-old_y;
child_x = orig_x+dx;
child_y = orig_y+dy;
gtk_fixed_move (GTK_FIXED(fixed), img_slot, child_x, child_y);
old_x = new_x;
old_y = new_y;
gdk_window_invalidate_rect (fixed_evbox->window, NULL, FALSE);
gdk_window_invalidate_rect (fixed->window, NULL, FALSE);
return TRUE;
}
}
}
else if (ev->type == GDK_EXPOSE) {
GtkStyle *style = w->style;
gdk_draw_rectangle (w->window, style->white_gc, TRUE, 0, 0, w->allocation.width, w->allocation.height);
gdk_draw_line (w->window, style->black_gc, 0, 0,
child_x+img_slot->allocation.width/2,
child_y+img_slot->allocation.height/2);
return TRUE;
}
else if (ev->type == GDK_BUTTON_RELEASE) {
gtk_grab_remove(gtk_grab_get_current ());
dragging = FALSE;
return TRUE;
}
return FALSE;
}
int main( int argc,
char *argv[] )
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window;
gint i;
/* Initialise GTK */
gtk_init (&argc, &argv);
/* Create a new window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Fixed Container");
/* Here we connect the "destroy" event to a signal handler */
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
/* Sets the border width of the window. */
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
/* Create a Fixed Container */
fixed = gtk_fixed_new ();
fixed_evbox = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (fixed_evbox), fixed);
gtk_container_add (GTK_CONTAINER (window), fixed_evbox);
gtk_widget_show (fixed);
img_slot = gtk_event_box_new ();
{
GtkWidget *img = gtk_image_new_from_file ("circle.png");
gtk_widget_show(img);
gtk_container_add (GTK_CONTAINER (img_slot), img);
}
set_shape_mask_from_file (img_slot, "circle.png");
gtk_widget_add_events (fixed_evbox,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK);
g_signal_connect(G_OBJECT(fixed_evbox), "event", G_CALLBACK(img_event), 0);
/* This packs the event box into the fixed containers window. */
gtk_fixed_put (GTK_FIXED (fixed), img_slot, 150, 150);
/* Display the window */
gtk_widget_show_all (window);
/* Enter the event loop */
gtk_main ();
return 0;
}
X--------------------------
Here the circle.png image is a big black circle (100x100) on a transparent background.
Is this a bug or I'm missing something?
I'm using gtk 2.8.0 / 2.8.3 on win32 platform.
Thanks,
Calin |
|
| Back to top |
|
 |
MacSlow Familiar Face
Joined: 21 Sep 2005 Posts: 17 Location: Aachen, Germany
|
Posted: Wed Sep 21, 2005 3:29 pm Post subject: |
|
|
I tried your code on Linux with gtk+-2.6.7 (everything works as expected) and gtk+-2.8.3 (the shape-mask just doesn't seem to get applied). The reason for not working under gtk+-2.8.3 I don't know. But my guess is, that it maybe some "side-effect" of gtk+-2.8.3 internally using cairo for all its rendering. You may have to try a differnt approach (using cairo). A short excerpt from the gtk+-2.8.3 docs:
| Quote: | | Cairo is a graphics library that supports vector graphics and image compositing that can be used with GDK. Since 2.8, GTK+ does most of its drawing using Cairo. |
I'm afraid I cannot give you more hints than this, as I still have to learn about cairo-utilization myself.
EDIT: You might want to look at this page with a nice sourcecode/screenshot table to get you started.
Best regards...
MacSlow |
|
| Back to top |
|
 |
|
Powered by phpBB © 2001, 2005 phpBB Group CodeBB 1.0 Beta 2
|