10.3. Gtk2::Gdk - On Screen Clock

To display text on screen, we will normally use a Gtk2::Label. This does not allow us to have a transparent background. If we want to display text with a transparent background, it becomes more involved. We have to dig deeper and use some of the Gtk2::Gdk classes to accomplish our goal.

Table 10-5. Gtk2 object classes used

Gtk2 Class Name
Gtk2::Window
Gtk2::VBox
Gtk2::EventBox
Gtk2::Image
Gtk2::DrawingArea
Gtk2::Style
Gtk2::Pango

Table 10-6. Gtk2::Gdk object classes used

Gtk2::Gdk Class Name
Gtk2::Gdk::Pixmap
Gtk2::Gdk::Pixbuf
Gtk2::Gdk::Colormap
Gtk2::Gdk::Window
Gtk2::Gdk::Drawable
Gtk2::Gdk::Event

Table 10-7. Special Class used

Gtk2 Class Name
Glib::MainLoop

10.3.1. Classes new to us.

In the tables above there are classes new to us. This section will briefly list each one plus their use in our application.

Gtk2::Style: Almost every displayable Gtk2 widget has a style associated to it. You can modify or use certain methods from a widget's associated style class.

Gtk2::Pango: This is used especially for internationalization purposes. It also allows you to modify how text will be presented on screen

Gtk2::DrawingArea: We will use this as a simple canvas to draw pango text upon. It can also be used to draw lines, dots, colors etc upon.

Gtk2::Gdk::Pixbuf: This is like the word says, a buffer of pixels. These pixels can be sourced from various places, the Gtk2::Gdk::Pixbuf is used on the X client where the Gtk2::Gdk::Pixmap is used on the X server. The pixels can be modified.(read image manipulation) We can change certain colors to a alpha channel. Scaling is also possible.

Gtk2::Gdk::Colormap: Colormaps are used to store the mappings between the RGB values you ask for and the actual, hardware-dependent values used to display those colors. We will use the default system colormap.

Gtk2::Gdk::Drawable: This class allows you to use the Gtk2::DrawingArea and the Gtk2::Gdk::Pixmap as a canvas, by supplying various drawing methods. Both of them are subclasses of Gtk2::Gdk::Drawable

10.3.2. Discussion on the program.

The program will be implemented as follows:

We will now look what the sub that gets called every second does.

10.3.3. The program's interface.

Figure 10-2. Gtk2::Gdk - On Screen Clock

10.3.4. The Code

The program can be found here: 'OSD Clock'

	
  1 #!/usr/bin/perl -w
  2 
  3 use strict;
  4 use Glib qw/TRUE FALSE/;
  5 use Gtk2 '-init';
  6 
  7 #add a timer to run each second
  8 Glib::Timeout->add (1000,\&new_screen);
  9 
 10 #create a popup window -> this allow us to modify its shape to 
 11 #that of a Gtk::Gdk::Pixmap class.
 12 my $window= Gtk2::Window->new('popup');
 13 
 14 	
 15 	#standard packing widget
 16 	my $vbox = Gtk2::VBox->new(FALSE,0);
 17 
 18 		my $eventbox = Gtk2::EventBox->new();
 19 		$window->signal_connect('button-press-event' => sub{ exit(0);});
 20 		#create an image containing nothing, this will be set each time 
 21 		#the &new_screen sub runs
 22 		my $img = Gtk2::Image->new_from_pixmap (undef, undef);
 23 		
 24 		$eventbox->add($img);
 25 	
 26 	$vbox->pack_start($eventbox,FALSE,FALSE,0);
 27 	
 28 $window->add($vbox);
 29 
 30 $window->set_position('center-always');
 31 #show all BEFORE we add $drawing_area - we do not want to show the drawing
 32 #area, we only use it as a working surface.
 33 $window->show_all();
 34 
 35 	#Create a drawing area, and set is big enough to hold the maximum size our 
 36 	#text will ever be.
 37 	my $drawing_area = Gtk2::DrawingArea->new;
 38 	$drawing_area->set_size_request (1600, 1600);
 39 	$vbox->pack_start($drawing_area,FALSE,FALSE,0);
 40 	
 41 	#realize it, since it will not be displayed, but we need to 
 42 	#get hold of the Gdk classes that needs it to be either shown,
 43 	#or realized
 44 	$drawing_area->realize;
 45 		#create a new pango layout for this drawing area 
 46 		#this is a method from the Gtk2::Widged class
 47 		my $pango_layout = $drawing_area->create_pango_layout("");
 48 		#get the defalt colormap (will be needed later on)
 49 		my $colormap = Gtk2::Gdk::Colormap->get_system;
 50 	#initial paint of screen
 51 	&new_screen;
 52 
 53 Gtk2->main;
 54 	
 55 sub new_screen {
 56 
 57 	#this sub will get a new value of text, and display it on the screen in a shaped 
 58 	#window, to get there needs a few steps
 59 
 60 	#get the text that we want to display on the screen.
 61 	my $ts = ret_time();
 62 	
 63 	#Set our pango layout, to reflect the text and format that we want.
 64 	#NOTE We deliberately set the background to a certain color to convert 
 65 	#that color to a alpha channel, that will give us the "clear" background. 
 66 	$pango_layout->set_markup("<span background = '#000000' foreground = '#FF0000' size = '20000' weight ='heavy'>Exact time:\n</span><span background = '#000000' foreground= '#00FF00' size='30000' weight = 'ultralight'><i><u>$ts</u></i></span>");
 67 	
 68 	#Get the size of this layout after the text was set.
 69 	my($pango_w,$pango_h)=$pango_layout->get_pixel_size;
 70 	
 71 	#Now we have the size, we can create a pixmap that will be the
 72 	#'Gtk2::Gdk::Drawable' that we will draw upon
 73 	my $pixmap = Gtk2::Gdk::Pixmap->new ($drawing_area->window,
 74                                     $pango_w,
 75                                     $pango_h,
 76                                     -1);
 77 	#Draw a black block on $pixmap the size of the pango text.
 78 	#This allow us to use newlines in the pango text, just make sure the pango
 79 	#background is also black, as to convert all the black to a alpha channel			    
 80 	$pixmap->draw_rectangle ($drawing_area->style->black_gc,
 81                         TRUE,
 82                         0, 0,
 83                         $pango_w,
 84                         $pango_h);
 85 			
 86 	#draw the pango layout on the drawable.
 87 	$pixmap->draw_layout($drawing_area->style->white_gc,0,0,$pango_layout);
 88 	
 89 	#create a Gtk2::Gdk::Pixbuf that we will use to grab the pango text from the
 90 	#drawable (Gtk2::Gdk::Pixmap which is a Gtk2::Gdk::Drawable) 
 91 	my $pixbuf = Gtk2::Gdk::Pixbuf->new ('rgb', TRUE, 8, $pango_w, $pango_h);
 92 	
 93 	#here we get create a pixbuff from the drawable, this is where we need the colormap
 94 	$pixbuf->get_from_drawable ($pixmap, $colormap, 0, 0, 0,0, $pango_w, $pango_h);
 95 		
 96 		#Remove the background (we use the color we specified as the pango text's
 97 		#background
 98 		$pixbuf = $pixbuf->add_alpha (TRUE, 0, 0 , 0);
 99 		
100 		#create a pixmap and mask from the Gtk2::Gdk::Pixbuf
101 		my ($pm, $m) = $pixbuf->render_pixmap_and_mask (255);
102 	#shrink our window to make sure the mask and pixmap will be on the same spot.
103 	$window->resize(4,4);
104 	#replace the old $img with the new pixmap and mask
105 	$img->set_from_pixmap ($pm, $m);
106 	
107 	#shape our window accordingly
108   	$window->shape_combine_mask ($m, 0, 0);
109   	
110 	return TRUE;
111 	
112 }
113 
114 
115 sub ret_time {
116 	#sub to return a string containing the time
117 my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)= localtime(time+3600);
118   	my @lst =("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
119   	my $thisday =$lst[$wday];
120   	$year = $year + 1900;
121   
122   	($sec =~ m/\d{2}/)||($sec = "0".$sec);
123   	($min =~ m/\d{2}/)||($min = "0".$min);
124   	($hour =~ m/\d{2}/)||($hour = "0".$hour);
125   	$mon = $mon +1;
126   	#print("\n");
127   	my $ts = "$thisday $mday/$mon/$year $hour:$min:$sec";
128 	
129 	return $ts;
130 }
131