System tray icon with Ruby and GTK2
- Date: 16 Jun 2010
- Category: development/ruby
- Tagged with: gtk, ruby, and system-tray
Everybody knows what system tray is. My friends (Hello, bigote and stanislavv!) were suggesting to start using FVWM and it’s pager instead of using system tray. But I was not inspired by pager. Probably because I was too lazy to try it in action for more than 1 minute. Anyway. One day I realized that I need something to notify me via system tray icon. So today I’m going to create a simple system tray icon in ruby with GTK step by step…
First of all let’s create a really simple (and absolutely dumb) version, which will only create a new system tray icon:
require 'gtk2'
Gtk::StatusIcon.new
Gtk.main
As you can see, first line require 'gtk2'
include GTK bindings. Then we
creating a new instance of Gtk::StatusIcon
. And finally run main GTK loop with
Gtk.main
. So basically first and the last lines are not very interesting and
all following code snippets will be without these two lines to keep you focused
on things that are really important ;)) But don’t forget them when you’ll be
trying these snippets…
If you tried the snippet above, you might notice that it adds a blank icon into
system tray. Looks at least strange, so let’s add some image to it. With GTK you
can use stock image, by setting stock
instance property of StatusIcon
:
si = Gtk::StatusIcon.new
si.stock = Gtk::Stock::DIALOG_INFO
Or you can you your own custom image by setting pixbuf
instance property:
si = Gtk::StatusIcon.new
si.pixbuf = Gdk::Pixbuf.new('/path/to/some/image.png')
You can specify both stock
and pixbuf
- but only the last one will be used.
So:
si = Gtk::StatusIcon.new
si.pixbuf = Gdk::Pixbuf.new('/path/to/some/image.png')
si.stock = Gtk::Stock::DIALOG_INFO
Will initiate a system tray icon with Gtk::Stock::DIALOG_INFO
stock image.
Now, when out system tray icon has a nice looking image, let’s add some
funkiness. Let’s make icon start blinking on left clicking it, and stop on
clicking it again. To make icon blink, you need to set blinking
instance
property to true
, e.g.:
si.blinking = true
But we want it to be turned on|off mouse left click. To do so, we need to
connect an activate
signal:
si.signal_connect('activate'){ |icon| icon.blinking = !(icon.blinking?) }
Cool! Now it’s cool! But don’t stop. Let’s add a pop-up menu for mouse right
clicking. To handle right click you need to use popup-menu
signal, something
like this:
si.signal_connect('popup-menu') do |tray, button, time|
# something to do?
end
Creating a popup-menu is little bit out of the scope, but to accomplish my first
system tray idiotic application, I will show it too. First, we need to create a
Gtk::Menu
instance:
menu = Gtk::Menu.new
Fill it with items, call show_all
instance method, and call popup
method
when we need it to be popped up. Now let’s create a new item quit item, make it
call Gtk.main_quit
on click, and append it to the menu:
menu = Gtk::Menu.new
quit = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
quit.signal_connect('activate'){ Gtk.main_quit }
menu.append(quit)
menu.show_all
So all we need no is to call menu.popup
inside popup-menu
signal handler:
si.signal_connect('popup-menu') do |icon, button, time|
menu.popup(nil, nil, button, time)
end
And altogether now:
require 'gtk2'
si = Gtk::StatusIcon.new
si.stock = Gtk::Stock::DIALOG_INFO
si.signal_connect('activate'){ |icon| icon.blinking = !(icon.blinking?) }
menu = Gtk::Menu.new
quit = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
quit.signal_connect('activate'){ Gtk.main_quit }
menu.append(quit)
menu.show_all
si.signal_connect('popup-menu') do |icon, button, time|
menu.popup(nil, nil, button, time)
end
Gtk.main
After all, I want to thank Vincent Carmona, whose example was a vivid tutorial of how to make a much smarter (than mine) system tray icon with GTK and ruby. You will find his example as an attachment to this post. I recommend you to read it, if you are still reading this ;))