LINUX.ORG.RU

Есть спецы по gtk2-perl? Прозрачность окна


0

0

Нашел в официальной документации пример на Си для gtk+ прозрачность окна. Код:

#include <gtk/gtk.h>
/* The expose event handler for the event box.
 *
 * This function simply draws a transparency onto a widget on the area
 * for which it receives expose events.  This is intended to give the
 * event box a "transparent" background.
 *
 * In order for this to work properly, the widget must have an RGBA
 * colourmap.  The widget should also be set as app-paintable since it
 * doesn't make sense for GTK+ to draw a background if we are drawing it
 * (and because GTK+ might actually replace our transparency with its
 * default background colour).
 */
static gboolean
transparent_expose (GtkWidget      *widget,
                    GdkEventExpose *event)
{
  cairo_t *cr;
  cr = gdk_cairo_create (widget->window);
  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
  gdk_cairo_region (cr, event->region);
  cairo_fill (cr);
  cairo_destroy (cr);
  return FALSE;
}
/* The expose event handler for the window.
 *
 * This function performs the actual compositing of the event box onto
 * the already-existing background of the window at 50% normal opacity.
 *
 * In this case we do not want app-paintable to be set on the widget
 * since we want it to draw its own (red) background. Because of this,
 * however, we must ensure that we use g_signal_connect_after so that
 * this handler is called after the red has been drawn. If it was
 * called before then GTK would just blindly paint over our work.
 *
 * Note: if the child window has children, then you need a cairo 1.16
 * feature to make this work correctly.
 */
static gboolean
window_expose_event (GtkWidget      *widget,
                     GdkEventExpose *event)
{
  GdkRegion *region;
  GtkWidget *child;
  cairo_t *cr;
  /* get our child (in this case, the event box) */
  child = gtk_bin_get_child (GTK_BIN (widget));
  /* create a cairo context to draw to the window */
  cr = gdk_cairo_create (widget->window);
  /* the source data is the (composited) event box */
  gdk_cairo_set_source_pixmap (cr, child->window,
                               child->allocation.x,
                               child->allocation.y);
  /* draw no more than our expose event intersects our child */
  region = gdk_region_rectangle (&child->allocation);
  gdk_region_intersect (region, event->region);
  gdk_cairo_region (cr, region);
  cairo_clip (cr);
  /* composite, with a 50% opacity */
  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
  cairo_paint_with_alpha (cr, 0.5);
  /* we're done */
  cairo_destroy (cr);
  return FALSE;
}
int
main (int argc, char **argv)
{
  GtkWidget *window, *event, *button;
  GdkScreen *screen;
  GdkColormap *rgba;
  GdkColor red;
  gtk_init (&argc, &argv);
  /* Make the widgets */
  button = gtk_button_new_with_label ("A Button");
  event = gtk_event_box_new ();
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  /* Put a red background on the window */
  gdk_color_parse ("red", &red);
  gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
  /* Set the colourmap for the event box.
   * Must be done before the event box is realised.
   */
  screen = gtk_widget_get_screen (event);
  rgba = gdk_screen_get_rgba_colormap (screen);
  gtk_widget_set_colormap (event, rgba);
  /* Set our event box to have a fully-transparent background
   * drawn on it. Currently there is no way to simply tell GTK+
   * that "transparency" is the background colour for a widget.
   */
  gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
  g_signal_connect (event, "expose-event",
                    G_CALLBACK (transparent_expose), NULL);
  /* Put them inside one another */
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
  gtk_container_add (GTK_CONTAINER (window), event);
  gtk_container_add (GTK_CONTAINER (event), button);
  /* Realise and show everything */
  gtk_widget_show_all (window);
  /* Set the event box GdkWindow to be composited.
   * Obviously must be performed after event box is realised.
   */
  gdk_window_set_composited (event->window, TRUE);
  /* Set up the compositing handler.
   * Note that we do _after_ so that the normal (red) background is drawn
   * by gtk before our compositing occurs.
   */
  g_signal_connect_after (window, "expose-event",
                          G_CALLBACK (window_expose_event), NULL);
  gtk_main ();
  return 0;
}

Захотел написать аналог на gtk2-perl но не работает :( показывает красное окошко и абсолютно не прозрачное... видимо где то ошибся. Где? Код:

#!/usr/bin/perl -w

use strict;
use warnings;
use Glib qw(TRUE FALSE);
use Gtk2 '-init';

sub transparent_expose
{
	my ($widget, $event) = @_;
	my $cr = Gtk2::Gdk::Cairo::Context->create($widget->window);
	$cr->set_operator("clear");
	$cr->region($event->region);
	$cr->fill;
	return FALSE;
}


sub window_expose_event
{
	my ($widget, $event) = @_;
	my $region;
	my $child;
	my $cr;
	$child = $widget->get_child();
	$cr = Gtk2::Gdk::Cairo::Context->create($widget->window);	
	$cr->set_source_pixmap( Gtk2::Gdk::Pixmap->new ($child->window,$child->allocation->width,$child->allocation->height,-1),$child->allocation->x,$child->allocation->y);
#$cr->set_source_pixmap($child->window,$child->allocation->x,$child->allocation->y);
	$region = Gtk2::Gdk::Region->rectangle($child->allocation);
	$region->intersect($event->region);
	$cr->region($region);
	$cr->clip();
	$cr->set_operator("over");
	$cr->paint_with_alpha(0.5);
	return FALSE;
}


#main
{
	my $button = Gtk2::Button->new_with_label("A Button");
	my $event = Gtk2::EventBox->new();
	my $window = Gtk2::Window->new('toplevel');
	$window->modify_bg("GTK_STATE_NORMAL",Gtk2::Gdk::Color->parse('red'));
	my $screen = $event->get_screen();
	my $rgba = $screen->get_rgba_colormap();
	$event->set_colormap($rgba);
	$event->set_app_paintable(TRUE);
	$event->signal_connect("expose-event",\&transparent_expose);
	$window->set_border_width(10);
	$window->add($event);
	$event->add($button);
	$window->show_all();
	$event->window->set_composited(TRUE);
	$window->signal_connect_after("expose-event",\&window_expose_event);
	Gtk2->main;
} 

Прошу заметить, что в данном месте кода

	$cr->set_source_pixmap( Gtk2::Gdk::Pixmap->new ($child->window,$child->allocation->width,$child->allocation->height,-1),$child->allocation->x,$child->allocation->y);
#$cr->set_source_pixmap($child->window,$child->allocation->x,$child->allocation->y);

я специально оставил два варианта, поскольку на тот, что за коменчен ругается perl, говорит что

*** unhandled exception in callback:
***   Gtk2::Gdk::Window=HASH(0x840e460) is not of type Gtk2::Gdk::Pixmap at ./test5.pl line 30.
***  ignoring at ./test5.pl line 58.

хотя странно ведь вдроде Gtk2::Gdk::Window должен автоматом преобразовываться в Gtk2::Gdk::Pixmap, а может я ошибаюсь.

В общем как подправить второй исходник чтоб работала прозрачность?

★★★

Версия Gtk2+ в примере и в твоей системе совпадает ?

anonymous
()

Ты ошибся, думая что перловые биндинги к гтк обновляются с той же скоростью, что и сам гтк.

anonymous
()
Ответ на: комментарий от vilfred

> напиши в их лист разработки

Так может я ошибся переводя код из GTK2+ в gtk2-perl

> Версия Gtk2+ в примере и в твоей системе совпадает ?

Что ты имеешь ввиду?

Mrak ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.