Details

[Home]

Issue of the Implementation # D0140

Brief

The function gdk_window_merge_child_shapes() doesn't behave like it is described in standard LSB 3.2

Detailed Description

According to the documentation the function gdk_window_merge_child_shapes() should set the shape mask of the window to the union of all masks for the window and its children, but it behaves unexpectedly

Problem location(s) in the standard

Linux Standard Base Desktop Specification 3.2. Chapter 15. Libraries. 15.21.1.1. Interfaces for GTK Drawing toolkit that refers http://www.gtk.org/api/2.6/gdk/gdk-Windows.html#gdk-window-merge-child-shapes

Example

#include <gdk/gdk.h>
#include <glib.h>
#include <stdio.h>

int main (int argc, char **argv)
{
	GdkWindowAttr parent_attr;
	GdkWindowAttr child1_attr;
	GdkWindowAttr child2_attr;
	GdkWindow *parent_window = NULL;
	GdkWindow *child1_window = NULL;
	GdkWindow *child2_window = NULL;
	GdkWindow *returned_window = NULL;
	GdkRegion *shape_region = NULL;
	GdkRegion *exp_region = NULL;
	GdkRectangle rect;
	GdkColormap *colormap = NULL;
	GdkColor color;
	GdkColor ret_color;
	GdkImage *image = NULL;
	int i;
	int j;

	gdk_init(&argc, &argv);
	
	colormap = gdk_colormap_get_system();
	if(colormap == NULL)
	{
		printf("The gdk_colormap_get_system function returned NULL, unable to create a GdkColormap.\n");
		return 0;
	}
	
	//creating three windows: one parent and two child windows
	parent_attr.title = "PARENT_WINDOW";
	parent_attr.x = 0;
	parent_attr.y = 0;
	parent_attr.width = 700;
	parent_attr.height = 800;
	parent_attr.wclass = GDK_INPUT_OUTPUT;
	parent_attr.window_type = GDK_WINDOW_TOPLEVEL;

	child1_attr.title = "CHILD1_WINDOW";
	child1_attr.x = 100;
	child1_attr.y = 200;
	child1_attr.width = 250;
	child1_attr.height = 300;
	child1_attr.wclass = GDK_INPUT_OUTPUT;
	child1_attr.window_type = GDK_WINDOW_TOPLEVEL;

	child2_attr.title = "CHILD2_WINDOW";
	child2_attr.x = 450;
	child2_attr.y = 100;
	child2_attr.width = 200;
	child2_attr.height = 600;
	child2_attr.wclass = GDK_INPUT_OUTPUT;
	child2_attr.window_type = GDK_WINDOW_TOPLEVEL;
	
	parent_window = gdk_window_new(NULL, &parent_attr, GDK_WA_X | GDK_WA_Y |GDK_WA_TITLE);
	child1_window = gdk_window_new(NULL, &child1_attr, GDK_WA_X | GDK_WA_Y |GDK_WA_TITLE);
	child2_window = gdk_window_new(NULL, &child2_attr, GDK_WA_X | GDK_WA_Y |GDK_WA_TITLE);
	if(parent_window == NULL || child1_window == NULL || child2_window == NULL)
	{
		printf("The gdk_window_new function returned NULL, unable to create a GdkWindow.\n");
		return 0;
	}
	
	gdk_window_reparent(child1_window, parent_window, 100, 200);
	gdk_window_reparent(child2_window, parent_window, 450, 100);

	gdk_window_show(parent_window);
	gdk_window_show(child1_window);
	gdk_window_show(child2_window);
	
	//setting background for windows
	color.red = 100 * (65535 / 255);
	color.green = 50 * (65535 / 255);
	color.blue = 100 * (65535 / 255);

	gdk_rgb_find_color(colormap, &color);
	gdk_window_set_background(child1_window, &color);
	gdk_window_set_background(child2_window, &color);
	gdk_window_set_background(parent_window, &color);
	
	//setting shapes for windows
	rect.x = 0;
	rect.y = 0;
	rect.width = 100;
	rect.height = 100;
	shape_region = gdk_region_rectangle(&rect);
	exp_region = gdk_region_copy(shape_region);

	gdk_window_shape_combine_region(parent_window, shape_region, 0, 0);
	gdk_window_shape_combine_region(child1_window, shape_region, 0, 0);
	gdk_window_shape_combine_region(child2_window, shape_region, 0, 0);

	gdk_window_merge_child_shapes(parent_window);

	//making of the region thet should be set on the window (parent window) after call of the function gdk_window_merge_child_shapes
	gdk_region_offset(shape_region, child1_attr.x, child1_attr.y);
	gdk_region_union(exp_region, shape_region);
	gdk_region_offset(shape_region, child2_attr.x - child1_attr.x, child2_attr.y - child1_attr.y);
	gdk_region_union(exp_region, shape_region);

	//making a GdkImage from the window (parent window)
	image = gdk_drawable_copy_to_image(parent_window, NULL, 0, 0, 0, 0, parent_attr.width, parent_attr.height);
	if(image == NULL)
	{
		printf("The gdk_drawable_copy_to_image function returned NULL, unable to create a GdkImage.\n");
		return 0;
	}
	
	//checking if the right shape was set on the window (parent window)
	for(i = 0; i < parent_attr.width; ++i)
	{
		for(j = 0; j < parent_attr.height; ++j)
		{
			gdk_colormap_query_color(colormap, gdk_image_get_pixel(image, i, j), &ret_color);
			if(gdk_region_point_in(exp_region, i, j))
			{
				if(!gdk_color_equal(&ret_color, &color))
				{
					printf("(%d, %d) pixel's color havn't been set. Therefore (%d, %d) pixel hadn't been visible, but it should.", i, j, i, j);
					return 0; 
				}
			}
			else
			{
				if(gdk_color_equal(&ret_color, &color))
				{
					printf("(%d, %d) pixel's color shouldn't been set, because it should be transparent, but it was.", i, j);
					return 0;
				}
			}
		}
	}


	if(parent_window != NULL)
	{
		gdk_window_destroy(parent_window);
	}

	if(child1_window != NULL)
	{
		gdk_window_destroy(child1_window);
	}

	if(child2_window != NULL)
	{
		gdk_window_destroy(child2_window);
	}

	if(image != NULL)
	{
		g_object_unref(image);
	}

	if(shape_region != NULL)
	{
		gdk_region_destroy(shape_region);
	}

	if(exp_region != NULL)
	{
		gdk_region_destroy(exp_region);
	}

	if(colormap != NULL)
	{
		g_object_unref(colormap);
	}

 	return 0;
}

Component

gtk+ 2.18 or early

Accepted

Gnome Bugzilla, 596067

[Home]