Re: Problem setting icon for Gtk2::StatusIcon


I think, based on how Gtk2::TrayIcon worked, that, at least on linux,
Gtk2::StatusIcon works by creating a widget. And, like other widgets,
drawing the widget, and responding to resize event, is done in the main
loop of your program. To make things worse, the widget interacts with
widgets from other process (the gnome panel).
So what I think is happening, is that when you change the icon, not all
needed events are generated right away, as some are only generated after
an other process has replied (maybe there is a size negotiation going
on, between your widget and the panel), so the "while
Gtk2->events_pending" loop finishes before all the work is done.

This explanation makes sense and fits my observation, although I don't
see why a resize event is being emitted when I change the icon to
another one of the same size. Unless, of course, calling
$icon->set_from_stock() makes Gtk2 somehow cause the tray
(unnecessarily) to resize the widget.

However, you have brought me onto the right track. The code below
using Gtk::TrayIcon works as expected. Instead of changing the
container (?) widget (status_icon) I only change the contents of the
image. The problem is that using Gtk::TrayIcon is discouraged. I'd
wish to know how to obtain the same effect with StatusIcon. (I'd
rather not use threads if I can avoid it; I know how to do it, and I
think that it is an overkill). However, for now TrayIcon will do.



use strict   ;
use warnings ;
use Gtk2::TrayIcon;


my $status_icon = Gtk2::TrayIcon->new("test");
my $image       = Gtk2::Image->new_from_stock('gtk-apply', 'menu' ) ;

$status_icon->add( $image ) ;

my $timer = Glib::Timeout->add( 1000, \&update, $image ) ;

Gtk2->main() ;

exit( 0 ) ;

sub update {
  my $image = shift ;
  $image->set_from_stock('gtk-refresh', 'menu' ) ;
  while( Gtk2->events_pending() ) { Gtk2->main_iteration() ; }
  sleep 5 ;
  $image->set_from_stock('gtk-apply', 'menu' ) ;

  return 1 ;

I doubt that there is an easy way to fix that, gtk2 is made to have a
main loop running.
Adding a main loop may not be so hard.
- if the long calculating part is done in another process, you can
launch it in a way that doesn't interrupt the main loop, and set up a
watch (for example on the standard output file descriptor of the
process) to generate a signal once it's finished.
- if it's perl code, there may be an easy way to do small chunks of it
in an idle callback. Or you may launch it in another process.


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