summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog27
-rw-r--r--ChangeLog.pre-2-1027
-rw-r--r--ChangeLog.pre-2-827
-rw-r--r--docs/reference/gdk/gdk-sections.txt2
-rw-r--r--gdk/gdk.symbols2
-rw-r--r--gdk/gdkrgb.c92
-rw-r--r--gdk/gdkscreen.h3
-rw-r--r--gdk/linux-fb/gdkscreen-fb.c16
-rw-r--r--gdk/win32/gdkscreen-win32.c16
-rw-r--r--gdk/x11/gdkcolor-x11.c12
-rw-r--r--gdk/x11/gdkdrawable-x11.c24
-rw-r--r--gdk/x11/gdkscreen-x11.c68
-rw-r--r--gdk/x11/gdkscreen-x11.h4
-rw-r--r--gdk/x11/gdkvisual-x11.c19
-rw-r--r--tests/testgtk.c253
15 files changed, 559 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 50564b3240..005494f7fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2005-05-09 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br):
+ Fill in unused bits so they can be used for the depth-32 target case.
+ Rewrite so that that gives a marginal speedup rather than a
+ marginal slowdown. (on x86)
+
+ * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
+ Add gdk_screen_get_rgba_colormap/visual to get a visual for
+ windows with an alpha channel, if one exists.
+
+ * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
+ Stub out gdk_screen_get_rgba_colormap/visual.
+
+ * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
+ "unused" wasn't right for depth == 32, since it depended on
+ shifting by 32.
+
+ * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
+ Keith Packard,
+ http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)
+
+ * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+ Implement again, without using Xft.
+
+ * tests/testgtk.c: Add a test for windows with an alpha channel.
+
2005-05-09 Matthias Clasen <mclasen@redhat.com>
* autogen.sh: Revert accidental commit.
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 50564b3240..005494f7fd 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,30 @@
+2005-05-09 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br):
+ Fill in unused bits so they can be used for the depth-32 target case.
+ Rewrite so that that gives a marginal speedup rather than a
+ marginal slowdown. (on x86)
+
+ * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
+ Add gdk_screen_get_rgba_colormap/visual to get a visual for
+ windows with an alpha channel, if one exists.
+
+ * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
+ Stub out gdk_screen_get_rgba_colormap/visual.
+
+ * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
+ "unused" wasn't right for depth == 32, since it depended on
+ shifting by 32.
+
+ * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
+ Keith Packard,
+ http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)
+
+ * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+ Implement again, without using Xft.
+
+ * tests/testgtk.c: Add a test for windows with an alpha channel.
+
2005-05-09 Matthias Clasen <mclasen@redhat.com>
* autogen.sh: Revert accidental commit.
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 50564b3240..005494f7fd 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,30 @@
+2005-05-09 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br):
+ Fill in unused bits so they can be used for the depth-32 target case.
+ Rewrite so that that gives a marginal speedup rather than a
+ marginal slowdown. (on x86)
+
+ * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
+ Add gdk_screen_get_rgba_colormap/visual to get a visual for
+ windows with an alpha channel, if one exists.
+
+ * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
+ Stub out gdk_screen_get_rgba_colormap/visual.
+
+ * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
+ "unused" wasn't right for depth == 32, since it depended on
+ shifting by 32.
+
+ * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
+ Keith Packard,
+ http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)
+
+ * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+ Implement again, without using Xft.
+
+ * tests/testgtk.c: Add a test for windows with an alpha channel.
+
2005-05-09 Matthias Clasen <mclasen@redhat.com>
* autogen.sh: Revert accidental commit.
diff --git a/docs/reference/gdk/gdk-sections.txt b/docs/reference/gdk/gdk-sections.txt
index 10f911d383..db2f0e264f 100644
--- a/docs/reference/gdk/gdk-sections.txt
+++ b/docs/reference/gdk/gdk-sections.txt
@@ -197,6 +197,8 @@ gdk_screen_get_system_colormap
gdk_screen_get_system_visual
gdk_screen_get_rgb_colormap
gdk_screen_get_rgb_visual
+gdk_screen_get_rgba_colormap
+gdk_screen_get_rgba_visual
gdk_screen_get_root_window
gdk_screen_get_display
gdk_screen_get_number
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index a7883569be..93448836dc 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -992,6 +992,8 @@ gdk_screen_get_default_colormap
gdk_screen_set_default_colormap
gdk_screen_get_n_monitors
gdk_screen_get_monitor_geometry
+gdk_screen_get_rgba_colormap
+gdk_screen_get_rgba_visual
gdk_screen_make_display_name
#endif
#endif
diff --git a/gdk/gdkrgb.c b/gdk/gdkrgb.c
index e8c1e53602..d78584216d 100644
--- a/gdk/gdkrgb.c
+++ b/gdk/gdkrgb.c
@@ -719,6 +719,23 @@ gdk_rgb_get_info_from_colormap (GdkColormap *cmap)
return image_info;
}
+static guint32
+gdk_rgb_alpha_mask (GdkRgbInfo *image_info)
+{
+ guint padding;
+
+ /* Shifting by >= width-of-type isn't defined in C */
+ if (image_info->visual->depth >= 32)
+ padding = 0;
+ else
+ padding = ((~(guint32)0)) << image_info->visual->depth;
+
+ return ~(image_info->visual->red_mask |
+ image_info->visual->green_mask |
+ image_info->visual->blue_mask |
+ padding);
+}
+
static gulong
gdk_rgb_xpixel_from_rgb_internal (GdkColormap *colormap,
guint16 r, guint16 g, guint16 b)
@@ -767,6 +784,7 @@ gdk_rgb_xpixel_from_rgb_internal (GdkColormap *colormap,
pixel = (unused + ((r >> (16 - image_info->visual->red_prec)) << image_info->visual->red_shift) +
((g >> (16 - image_info->visual->green_prec)) << image_info->visual->green_shift) +
((b >> (16 - image_info->visual->blue_prec)) << image_info->visual->blue_shift));
+ pixel |= gdk_rgb_alpha_mask (image_info);
}
else if (image_info->visual->type == GDK_VISUAL_STATIC_GRAY ||
image_info->visual->type == GDK_VISUAL_GRAYSCALE)
@@ -2126,11 +2144,10 @@ gdk_rgb_convert_0888 (GdkRgbInfo *image_info, GdkImage *image,
guchar *buf, int rowstride,
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
- int x, y;
- guchar *obuf;
+ int y, w;
+ guchar *obuf, *p;
gint bpl;
guchar *bptr, *bp2;
- int r, g, b;
bptr = buf;
bpl = image->bpl;
@@ -2138,13 +2155,16 @@ gdk_rgb_convert_0888 (GdkRgbInfo *image_info, GdkImage *image,
for (y = 0; y < height; y++)
{
bp2 = bptr;
- for (x = 0; x < width; x++)
+ p = obuf;
+ w = width;
+ while (w--)
{
- r = bp2[0];
- g = bp2[1];
- b = bp2[2];
- ((guint32 *)obuf)[x] = (r << 16) | (g << 8) | b;
+ p[0] = bp2[2];
+ p[1] = bp2[1];
+ p[2] = bp2[0];
+ p[3] = 0xff;
bp2 += 3;
+ p += 4;
}
bptr += rowstride;
obuf += bpl;
@@ -2157,11 +2177,10 @@ gdk_rgb_convert_0888_br (GdkRgbInfo *image_info, GdkImage *image,
guchar *buf, int rowstride,
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
- int x, y;
- guchar *obuf;
+ int y, w;
+ guchar *obuf, *p;
gint bpl;
guchar *bptr, *bp2;
- int r, g, b;
bptr = buf;
bpl = image->bpl;
@@ -2169,13 +2188,16 @@ gdk_rgb_convert_0888_br (GdkRgbInfo *image_info, GdkImage *image,
for (y = 0; y < height; y++)
{
bp2 = bptr;
- for (x = 0; x < width; x++)
+ p = obuf;
+ w = width;
+ while (w--)
{
- r = bp2[0];
- g = bp2[1];
- b = bp2[2];
- ((guint32 *)obuf)[x] = (b << 24) | (g << 16) | (r << 8);
+ p[0] = 0xff;
+ p[1] = bp2[0];
+ p[2] = bp2[1];
+ p[3] = bp2[2];
bp2 += 3;
+ p += 4;
}
bptr += rowstride;
obuf += bpl;
@@ -2232,6 +2254,7 @@ gdk_rgb_convert_truecolor_lsb (GdkRgbInfo *image_info, GdkImage *image,
gint b_right, b_left;
gint bpp;
guint32 pixel;
+ guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
gint i;
r_right = 8 - image_info->visual->red_prec;
@@ -2255,7 +2278,7 @@ gdk_rgb_convert_truecolor_lsb (GdkRgbInfo *image_info, GdkImage *image,
b = bp2[2];
pixel = ((r >> r_right) << r_left) |
((g >> g_right) << g_left) |
- ((b >> b_right) << b_left);
+ ((b >> b_right) << b_left) | alpha_mask;
for (i = 0; i < bpp; i++)
{
*obptr++ = pixel & 0xff;
@@ -2285,6 +2308,7 @@ gdk_rgb_convert_truecolor_lsb_d (GdkRgbInfo *image_info, GdkImage *image,
gint b_right, b_left, b_prec;
gint bpp;
guint32 pixel;
+ guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
gint i;
gint dith;
gint r1, g1, b1;
@@ -2319,7 +2343,7 @@ gdk_rgb_convert_truecolor_lsb_d (GdkRgbInfo *image_info, GdkImage *image,
b1 = b + (dith >> b_prec);
pixel = (((r1 - (r1 >> r_prec)) >> r_right) << r_left) |
(((g1 - (g1 >> g_prec)) >> g_right) << g_left) |
- (((b1 - (b1 >> b_prec)) >> b_right) << b_left);
+ (((b1 - (b1 >> b_prec)) >> b_right) << b_left) | alpha_mask;
for (i = 0; i < bpp; i++)
{
*obptr++ = pixel & 0xff;
@@ -2349,6 +2373,7 @@ gdk_rgb_convert_truecolor_msb (GdkRgbInfo *image_info, GdkImage *image,
gint b_right, b_left;
gint bpp;
guint32 pixel;
+ guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
gint shift, shift_init;
r_right = 8 - image_info->visual->red_prec;
@@ -2373,7 +2398,7 @@ gdk_rgb_convert_truecolor_msb (GdkRgbInfo *image_info, GdkImage *image,
b = bp2[2];
pixel = ((r >> r_right) << r_left) |
((g >> g_right) << g_left) |
- ((b >> b_right) << b_left);
+ ((b >> b_right) << b_left) | alpha_mask;
for (shift = shift_init; shift >= 0; shift -= 8)
{
*obptr++ = (pixel >> shift) & 0xff;
@@ -2402,6 +2427,7 @@ gdk_rgb_convert_truecolor_msb_d (GdkRgbInfo *image_info, GdkImage *image,
gint b_right, b_left, b_prec;
gint bpp;
guint32 pixel;
+ guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
gint shift, shift_init;
gint dith;
gint r1, g1, b1;
@@ -2437,7 +2463,7 @@ gdk_rgb_convert_truecolor_msb_d (GdkRgbInfo *image_info, GdkImage *image,
b1 = b + (dith >> b_prec);
pixel = (((r1 - (r1 >> r_prec)) >> r_right) << r_left) |
(((g1 - (g1 >> g_prec)) >> g_right) << g_left) |
- (((b1 - (b1 >> b_prec)) >> b_right) << b_left);
+ (((b1 - (b1 >> b_prec)) >> b_right) << b_left) | alpha_mask;
for (shift = shift_init; shift >= 0; shift -= 8)
{
*obptr++ = (pixel >> shift) & 0xff;
@@ -3110,27 +3136,43 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
(mask_bgr && byte_order == GDK_LSB_FIRST)))
conv = gdk_rgb_convert_888_msb;
#if G_BYTE_ORDER == G_BIG_ENDIAN
- else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ else if (bpp == 32 &&
+ (depth == 24 || depth == 32) &&
+ vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_rgb && byte_order == GDK_LSB_FIRST))
conv = gdk_rgb_convert_0888_br;
- else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ else if (bpp == 32 &&
+ (depth == 24 || depth == 32) &&
+ vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_rgb && byte_order == GDK_MSB_FIRST))
conv = gdk_rgb_convert_0888;
else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_bgr && byte_order == GDK_MSB_FIRST))
conv = gdk_rgb_convert_8880_br;
+ else if (bpp == 32 && depth == 32 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ (mask_rgb && byte_order == GDK_LSB_FIRST))
+ conv = gdk_rgb_convert_8880_br;
+ else if (bpp == 32 && depth == 32 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ (mask_rgb && byte_order == GDK_MSB_FIRST))
+ conv = gdk_rgb_convert_8880_br;
#else
- else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ else if (bpp == 32 &&
+ (depth == 24 || depth == 32) &&
+ vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_rgb && byte_order == GDK_MSB_FIRST))
conv = gdk_rgb_convert_0888_br;
- else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ else if (bpp == 32 &&
+ (depth == 24 || depth == 32) &&
+ vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_rgb && byte_order == GDK_LSB_FIRST))
conv = gdk_rgb_convert_0888;
else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_bgr && byte_order == GDK_LSB_FIRST))
conv = gdk_rgb_convert_8880_br;
+ else if (bpp == 32 && depth == 32 && vtype == GDK_VISUAL_TRUE_COLOR &&
+ (mask_rgb && byte_order == GDK_LSB_FIRST))
+ conv = gdk_rgb_convert_0888;
#endif
-
else if (vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST)
{
conv = gdk_rgb_convert_truecolor_lsb;
diff --git a/gdk/gdkscreen.h b/gdk/gdkscreen.h
index f527099f44..5a27cbe232 100644
--- a/gdk/gdkscreen.h
+++ b/gdk/gdkscreen.h
@@ -63,6 +63,9 @@ GdkColormap* gdk_screen_get_system_colormap (GdkScreen *screen);
GdkVisual* gdk_screen_get_system_visual (GdkScreen *screen);
GdkColormap *gdk_screen_get_rgb_colormap (GdkScreen *screen);
GdkVisual * gdk_screen_get_rgb_visual (GdkScreen *screen);
+GdkColormap *gdk_screen_get_rgba_colormap (GdkScreen *screen);
+GdkVisual * gdk_screen_get_rgba_visual (GdkScreen *screen);
+
GdkWindow * gdk_screen_get_root_window (GdkScreen *screen);
GdkDisplay * gdk_screen_get_display (GdkScreen *screen);
diff --git a/gdk/linux-fb/gdkscreen-fb.c b/gdk/linux-fb/gdkscreen-fb.c
index fd237c3fb4..ff19caaa98 100644
--- a/gdk/linux-fb/gdkscreen-fb.c
+++ b/gdk/linux-fb/gdkscreen-fb.c
@@ -82,6 +82,22 @@ gdk_screen_get_monitor_geometry (GdkScreen *screen,
dest->height = gdk_screen_height ();
}
+GdkColormap *
+gdk_screen_get_rgba_colormap (GdkScreen *screen)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return NULL;
+}
+
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return NULL;
+}
+
gint
gdk_screen_get_number (GdkScreen *screen)
{
diff --git a/gdk/win32/gdkscreen-win32.c b/gdk/win32/gdkscreen-win32.c
index a68d24c2c0..45e151a377 100644
--- a/gdk/win32/gdkscreen-win32.c
+++ b/gdk/win32/gdkscreen-win32.c
@@ -78,6 +78,22 @@ gdk_screen_get_monitor_geometry (GdkScreen *screen,
*dest = _gdk_monitors[num_monitor];
}
+GdkColormap *
+gdk_screen_get_rgba_colormap (GdkScreen *screen)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return NULL;
+}
+
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return NULL;
+}
+
gint
gdk_screen_get_number (GdkScreen *screen)
{
diff --git a/gdk/x11/gdkcolor-x11.c b/gdk/x11/gdkcolor-x11.c
index 9322e9391b..95fffe82b7 100644
--- a/gdk/x11/gdkcolor-x11.c
+++ b/gdk/x11/gdkcolor-x11.c
@@ -1130,8 +1130,16 @@ gdk_colormap_alloc_colors (GdkColormap *colormap,
/* If bits not used for color are used for something other than padding,
* it's likely alpha, so we set them to 1s.
*/
- guint32 unused = ~ (visual->red_mask | visual->green_mask | visual->blue_mask |
- (((~(guint32)0)) << visual->depth));
+ guint padding, unused;
+
+ /* Shifting by >= width-of-type isn't defined in C */
+ if (visual->depth >= 32)
+ padding = 0;
+ else
+ padding = ((~(guint32)0)) << visual->depth;
+
+ unused = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
+
colors[i].pixel = (unused +
((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c
index 71e02909f5..7922aaeee0 100644
--- a/gdk/x11/gdkdrawable-x11.c
+++ b/gdk/x11/gdkdrawable-x11.c
@@ -337,7 +337,29 @@ _gdk_x11_have_render (GdkDisplay *display)
static Picture
gdk_x11_drawable_get_picture (GdkDrawable *drawable)
{
- return None;
+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+
+ if (!impl->picture)
+ {
+ Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
+ XRenderPictFormat *format;
+
+ GdkVisual *visual = gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
+ if (!visual)
+ return None;
+
+ format = XRenderFindVisualFormat (xdisplay, GDK_VISUAL_XVISUAL (visual));
+ if (format)
+ {
+ XRenderPictureAttributes attributes;
+ attributes.graphics_exposures = False;
+
+ impl->picture = XRenderCreatePicture (xdisplay, impl->xid, format,
+ CPGraphicsExposure, &attributes);
+ }
+ }
+
+ return impl->picture;
}
static void
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 3ab2bfc8af..1dbff67c2e 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -288,6 +288,12 @@ gdk_screen_x11_dispose (GObject *object)
g_object_unref (screen_x11->default_colormap);
screen_x11->default_colormap = NULL;
+
+ if (screen_x11->rgba_colormap)
+ {
+ g_object_unref (screen_x11->rgba_colormap);
+ screen_x11->rgba_colormap = NULL;
+ }
screen_x11->root_window = NULL;
@@ -372,6 +378,68 @@ gdk_screen_get_monitor_geometry (GdkScreen *screen,
}
/**
+ * gdk_screen_get_rgba_colormap:
+ * @screen: a #GdkScreen.
+ *
+ * Gets a colormap to use for creating windows or pixmaps with an
+ * alpha channel. The windowing system on which GTK+ is running
+ * may not support this capability, in which case %NULL will
+ * be returned. Even if a non-%NULL value is returned, its
+ * possible that the window's alpha channel won't be honored
+ * when displaying the window on the screen: in particular, for
+ * X an appropriate windowing manager and compositing manager
+ * must be running to provide appropriate display.
+ *
+ * Return value: a colormap to use for windows with an alpha channel
+ * or %NULL if the capability is not available.
+ *
+ * Since: 2.8
+ **/
+GdkColormap *
+gdk_screen_get_rgba_colormap (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
+
+ if (!screen_x11->rgba_visual)
+ return NULL;
+
+ if (!screen_x11->rgba_colormap)
+ screen_x11->rgba_colormap = gdk_colormap_new (screen_x11->rgba_visual,
+ FALSE);
+
+ return screen_x11->rgba_colormap;
+}
+
+/**
+ * gdk_screen_get_rgba_visual:
+ * @screen: a #GdkScreen
+ *
+ * Gets a visual to use for creating windows or pixmaps with an
+ * alpha channel. See the docs for gdk_screen_get_rgba_colormap()
+ * for caveats.
+ *
+ * Return value: a visual to use for windows with an alpha channel
+ * or %NULL if the capability is not available.
+ *
+ * Since: 2.8
+ **/
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
+
+ return screen_x11->rgba_visual;
+}
+
+/**
* gdk_x11_screen_get_xscreen:
* @screen: a #GdkScreen.
* @returns: an Xlib <type>Screen*</type>
diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h
index fddc28dd04..aa08dca15b 100644
--- a/gdk/x11/gdkscreen-x11.h
+++ b/gdk/x11/gdkscreen-x11.h
@@ -76,11 +76,13 @@ struct _GdkScreenX11
gint navailable_types;
GHashTable *visual_hash;
GHashTable *colormap_hash;
+ GdkVisual *rgba_visual;
/* Colormap Part */
GdkColormap *default_colormap;
GdkColormap *system_colormap;
-
+ GdkColormap *rgba_colormap;
+
/* X settings */
XSettingsClient *xsettings_client;
guint xsettings_in_init : 1;
diff --git a/gdk/x11/gdkvisual-x11.c b/gdk/x11/gdkvisual-x11.c
index 95b2df7a2a..94d3687a11 100644
--- a/gdk/x11/gdkvisual-x11.c
+++ b/gdk/x11/gdkvisual-x11.c
@@ -257,11 +257,22 @@ _gdk_visual_init (GdkScreen *screen)
}
for (i = 0; i < nvisuals; i++)
- if (default_xvisual->visualid == visuals[i]->xvisual->visualid)
- {
+ {
+ if (default_xvisual->visualid == visuals[i]->xvisual->visualid)
screen_x11->system_visual = visuals[i];
- break;
- }
+
+ /* For now, we only support 8888 ARGB for the "rgba visual".
+ * Additional formats (like ABGR) could be added later if they
+ * turn up.
+ */
+ if (visuals[i]->visual.depth == 32 &&
+ (visuals[i]->visual.red_mask == 0xff0000 &&
+ visuals[i]->visual.green_mask == 0x00ff00 &&
+ visuals[i]->visual.blue_mask == 0x0000ff))
+ {
+ screen_x11->rgba_visual = GDK_VISUAL (visuals[i]);
+ }
+ }
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_MISC)
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 22919bd23c..b4480be8d4 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -148,6 +148,258 @@ destroy_tooltips (GtkWidget *widget, GtkWindow **window)
/*
+ * Windows with an alpha channel
+ */
+
+
+static gboolean
+on_alpha_window_expose (GtkWidget *widget,
+ GdkEventExpose *expose)
+{
+ cairo_t *cr;
+ cairo_pattern_t *pattern;
+ int radius;
+
+ cr = gdk_drawable_create_cairo_context (widget->window);
+
+ radius = MIN (widget->allocation.width, widget->allocation.height) / 2;
+ pattern = cairo_pattern_create_radial (widget->allocation.width / 2,
+ widget->allocation.height / 2,
+ 0.0,
+ widget->allocation.width / 2,
+ widget->allocation.height / 2,
+ radius * 1.33);
+
+ if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)))
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
+ else
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+ cairo_pattern_add_color_stop_rgba (pattern, 0.0,
+ 1.0, 0.75, 0.0, 1.0); /* solid orange */
+ cairo_pattern_add_color_stop_rgba (pattern, 1.0,
+ 1.0, 0.75, 0.0, 0.0); /* transparent orange */
+
+ cairo_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+static GtkWidget *
+build_alpha_widgets (void)
+{
+ GtkWidget *table;
+ GtkWidget *radio_button;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *entry;
+
+ table = gtk_table_new (1, 1, FALSE);
+
+ radio_button = gtk_radio_button_new_with_label (NULL, "Red");
+ gtk_table_attach (GTK_TABLE (table),
+ radio_button,
+ 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
+ gtk_table_attach (GTK_TABLE (table),
+ radio_button,
+ 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
+ gtk_table_attach (GTK_TABLE (table),
+ radio_button,
+ 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ gtk_table_attach (GTK_TABLE (table),
+ gtk_check_button_new_with_label ("Sedentary"),
+ 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+ gtk_table_attach (GTK_TABLE (table),
+ gtk_check_button_new_with_label ("Nocturnal"),
+ 1, 2, 1, 2,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+ gtk_table_attach (GTK_TABLE (table),
+ gtk_check_button_new_with_label ("Compulsive"),
+ 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
+ gtk_table_attach (GTK_TABLE (table),
+ radio_button,
+ 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
+ gtk_table_attach (GTK_TABLE (table),
+ radio_button,
+ 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ label = gtk_label_new (NULL);
+ gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+ gtk_table_attach (GTK_TABLE (table),
+ hbox,
+ 0, 1, 3, 4,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ return table;
+}
+
+static gboolean
+on_alpha_drawing_expose (GtkWidget *widget,
+ GdkEventExpose *expose)
+{
+ int x = widget->allocation.x;
+ int y = widget->allocation.y;
+ int width = widget->allocation.width;
+ int height = widget->allocation.height;
+ GdkPixbuf *pixbuf;
+ guchar *buffer;
+ guchar *p;
+ int i, j;
+
+ buffer = g_malloc (64 * 64 * 4);
+
+ gdk_draw_rectangle (widget->window, widget->style->black_gc, FALSE,
+ x, y,
+ width - 1, height - 1);
+
+ p = buffer;
+ for (i = 0; i < 64; i++) {
+ for (j = 0; j < 64; j++) {
+ *(p++) = i * 4 + 3;
+ *(p++) = 0;
+ *(p++) = j + 4 + 3;
+ *(p++) = MIN (255, ((32 - i) * (32 - i) + (32 - j) * (32 - j)) / 8);
+ }
+ }
+ p++;
+
+ gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
+ x + 18, y + (height - 64) /2,
+ 64, 64, GDK_RGB_DITHER_NORMAL, buffer, 64 * 4);
+
+ pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
+ 8, 64, 64, 4 * 64, NULL, NULL);
+
+ gdk_draw_pixbuf (widget->window, widget->style->black_gc, pixbuf,
+ 0, 0, x + width - 18 - 64, y + (height - 64) /2,
+ 64, 64, GDK_RGB_DITHER_NORMAL, 0, 0);
+
+ g_object_unref (pixbuf);
+
+ g_free (buffer);
+
+ return FALSE;
+}
+
+static GtkWidget *
+build_alpha_drawing ()
+{
+ GtkWidget *hbox;
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_set_size_request (hbox, 100, 100);
+
+ g_signal_connect (hbox, "expose-event",
+ G_CALLBACK (on_alpha_drawing_expose), NULL);
+
+ return hbox;
+}
+
+static void
+on_alpha_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen,
+ GtkWidget *label)
+{
+ GdkScreen *screen = gtk_widget_get_screen (widget);
+ GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
+
+ if (!colormap)
+ {
+ colormap = gdk_screen_get_rgb_colormap (screen);
+ gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
+ }
+ else
+ {
+ gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
+ }
+
+ gtk_widget_set_colormap (widget, colormap);
+}
+
+void
+create_alpha_window (GtkWidget *widget)
+{
+ static GtkWidget *window;
+
+ if (!window)
+ {
+ GtkWidget *vbox;
+ GtkWidget *label;
+
+ window = gtk_dialog_new_with_buttons ("Alpha Window",
+ GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
+ GTK_STOCK_CLOSE, 0,
+ NULL);
+
+ gtk_widget_set_app_paintable (window, TRUE);
+ g_signal_connect (window, "expose-event",
+ G_CALLBACK (on_alpha_window_expose), NULL);
+
+ vbox = gtk_vbox_new (FALSE, 8);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
+ TRUE, TRUE, 0);
+
+ label = gtk_label_new (NULL);
+
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0);
+
+ on_alpha_screen_changed (window, NULL, label);
+ g_signal_connect (window, "screen-changed",
+ G_CALLBACK (on_alpha_screen_changed), label);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &window);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show_all (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+/*
* Big windows and guffaw scrolling
*/
@@ -12860,6 +13112,7 @@ struct {
gboolean do_not_benchmark;
} buttons[] =
{
+ { "alpha window", create_alpha_window },
#ifdef G_OS_WIN32
/* dog slow on NT, no working at all on 9x */
{ "big windows", create_big_windows, TRUE },