Re: GtkWidgets and their underlying GdkWindows



On Tue, 04 Sep 2007 16:42:22 +1000
Andrew Cowie <andrew operationaldynamics com> wrote:

>We all "know" that some GtkWidgets have their own GdkWindows (ie
>GtkButtons), and some do not (ie GtkLabels). At least, that's what the
>documentation tells us.
>
>As I understand it, for GtkWidget* widget,
>
>    widget->window
>
>is this GdkWindow*, if so assigned.
>
>++
>
>I was working on writing a method to expose this in the Java bindings,
>and was somewhat surprised to find that all the Widgets in my little
>test app had the _same_ GdkWindow. Huh?


>I really would have expected the GtkButton and GtkLabel to have
>different GdkWindows. According to this, they're all writing to the same
>one.
>
>{shrug}
>
>This is not a problem; I'm just not sure how to explain it (and in turn
>document our binding of GdkWindow). My guess is either a) my app is too
>simple, or b) GTK is doing something smart under the hood and the
>original Xlib <-> GDK wrapping has long been superseded, perhaps by the
>Cairo drawing layer.
>
>Have things evolved from when the original API documentation was
>written, or am I just doing something really silly?

Hi, I usually do Perl, and don't have time to convert this to c, but
here is way to locate and change buttons.

Even though they are all in the same window, you can get the children
of the window, and write to their "paintable areas".

#!/usr/bin/perl
use warnings;
use strict;
use Glib qw/TRUE FALSE/;
use Gtk2 '-init';
use MIME::Base64;

my @rectangles; #global for storing icon locations

my $window = Gtk2::Window->new('toplevel');
$window->set_title('Embed test');
$window ->signal_connect( 'destroy' => \&delete_event );
$window->set_border_width(10);
$window->set_default_size(500,430);

my $vbox = Gtk2::VBox->new( FALSE, 6 );
$window->add($vbox);
$vbox->set_border_width(2);

my $hbox= Gtk2::HBox->new( FALSE, 6 );
$vbox->pack_end($hbox,FALSE,FALSE,0);
$hbox->set_border_width(2);
$hbox->set_size_request(500,48);

$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);

my $button = Gtk2::Button->new_from_stock('gtk-quit');
$hbox->pack_end( $button, FALSE, FALSE, 0 );
$button->signal_connect( clicked => \&delete_event );

my $button1 = Gtk2::Button->new('Set BG');
$hbox->pack_end( $button1, FALSE, FALSE, 0 );
$button1->signal_connect( clicked => \&set_bg,'single');

my $button2 = Gtk2::Button->new('Set BGauto');
$hbox->pack_end( $button2, FALSE, FALSE, 0 );
$button2->signal_connect( clicked => \&set_bg,'auto' );


my $button0 = Gtk2::Button->new('Clear');
$hbox->pack_end( $button0, FALSE, FALSE, 0 );
$button0->signal_connect( clicked => \&set_clear );

my $vbox1 = Gtk2::VBox->new( 0, 5 );
$vbox->pack_end ($vbox1, TRUE, TRUE, 0);

my $btn = Gtk2::Button->new_from_stock('gtk-quit');
$btn->signal_connect( 'clicked' => \&delete_event );

$window->show_all();
Gtk2->main;
#####################################
sub delete_event {
Gtk2->main_quit;
return FALSE;
}  
###############################################################
sub set_clear{
 
  my $gdkwindow = $window->window;
  foreach my $rectangle(@rectangles){  
     $gdkwindow->invalidate_rect ($rectangle,0);
  }

@rectangles = ();

return FALSE;
}
#################################################################
sub set_bg{
 my ($caller,$mode) = @_;
print "mode->$mode\n";

my $bunny = get_bunny();
               
# this properly renders it
my $pixbuf = do {
        my $loader = Gtk2::Gdk::PixbufLoader->new();
        $loader->write( $bunny );
        $loader->close();
        $loader->get_pixbuf();
    };
my ($x, $y) = ($pixbuf->get_width, $pixbuf->get_height);
#print "$x $y\n";
#print 'rowstride->', $pixbuf->get_rowstride,"\n";

#set the new pixbuff in the window
#the gdkwindow is the actual window on the screen
my $gdkwindow = $window->window;

#the gdkwindow children are buttons, not the packing boxes 
#the gdk window is the actual paintable surface on the screen,
# the children are areas of different painting, so the packing
#boxes are not gdk children, but the buttons are.
my @clist = $gdkwindow->get_children;
#print "@clist\n";
my $gdkwindowC = $clist[0]; #the first button is the exit

my ($x0, $y0, $width0, $height0, $depth) = $gdkwindowC->get_geometry;
print "geometry x0->$x0, y0->$y0, width->$width0, height->$height0, depth->$depth\n";

my ($drawable, $x_offset, $y_offset) = $gdkwindowC->get_internal_paint_info;
print "drawable->$drawable, x_offset->$x_offset, y_offset->$y_offset\n\n";

my $gc = Gtk2::Gdk::GC->new ($gdkwindow, undef);

#$pixbuf->render_to_drawable ($drawable, $gc, 
#   $src_x, $src_y, $dest_x, $dest_y, $width, $height, $dither, $x_dither, $y_dither)

if($mode eq 'single'){
   $pixbuf->render_to_drawable($gdkwindow, $gc,
                             0,0,$x0,$y0,$x,$y,'normal',0,0);
   my $rectangle = Gtk2::Gdk::Rectangle->new ($x0, $y0, $x, $y);
   push @rectangles, $rectangle;
}else{
   for(1..10){
              my $x1 = int rand $x0;
              my $y1 = int rand $y0;

      $pixbuf->render_to_drawable($gdkwindow, $gc,
                             0,0,$x1,$y1,$x,$y,'normal',0,0);
      
      my $rectangle = Gtk2::Gdk::Rectangle->new ($x1, $y1, $x, $y);
      push @rectangles, $rectangle;
  }

}

Gtk2->main_iteration while Gtk2->events_pending;
return FALSE;
}

#################################################################

sub get_bunny{

return  decode_base64(
'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjCAYAAACD1LrRAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
WXMAAAsSAAALEgHS3X78AAAAmElEQVRYw+1WQQ7AIAizxP9/mV121Gm0BZfYxNukKxSwlIPg75HG
MrGALkykfHjPBKmf+tbIAad/0Ngp3CHGIrnvEoco7xFDTf6lGMIeH6YaBNVYrTEUKYfYUGDW0bOI
t2qrTjVYNXa2f9SDAqt97I1AlMFST9pOIbjEYRuKsSS4fUZydcqSQOTzVubq/w+QmmVWtmIvFx08
tNghLUXwK/sAAAAASUVORK5CYII=');

}

__END__


zentara


-- 
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]