GTK+ Forums Forum Index GTK+ Forums
Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

shape masked widgets on gtk 2.8.x

 
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Programming
Author Message
Calin
Guest





PostPosted: Wed Sep 21, 2005 7:01 am    Post subject: shape masked widgets on gtk 2.8.x Reply with quote

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

PostPosted: Wed Sep 21, 2005 3:29 pm    Post subject: Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Programming All times are GMT
Page 1 of 1

 


Powered by phpBB © 2001, 2005 phpBB Group
CodeBB 1.0 Beta 2
Protected by Anti-Spam ACP