tags:

views:

475

answers:

2

I have a crossplatform app that has a gtk.StatusIcon sitting in the tray, and a right click context menu. The problem is: on Windows machines the placement of the menu is awful. The top of the menu starts at the mouse pointer and so most of the menu extends below the bottom of the screen. This can then be scrolled up and is usable, but it is a bit of a pain for the user.

Another related question, is it possible to make the menu disappear if the user clicks somewhere else on the screen?

+1  A: 

To avoid this "scrolling menu" problem on Windows you need to replace gtk.status_icon_position_menu with None in "popup-menu" signal callback.

def popup_menu_cb(status_icon, button, activate_time, menu):
    menu.popup(None, None, None, button, activate_time)

The menu will show on the mouse cursor but that's how all windows programs do it.

Don't know how to hide it though... the only thing I found to work is pressing a mouse button on the menu and releasing it outside. :P

Ivan Baldin
great, thanks!This other problem is not such a big deal, I guess I can live with it.
wodemoneke
A: 

You can hide the popup when the mouse moves away by enabling the leave_notify and enter_notify events on the popup. Then use these to set and clear a time stamp. Then in a timer callback created with gobject.timeout_add() check to see if the mouse has been away from the popup menu for a certain amount of time. If it has then hide() the popup and clear the timer.

Here are the event and timer call backs I'm using:

. . .
    self.mouse_in_tray_menu = None
    gobject.timeout_add(500, self.check_hide_popup)
. . .

def on_tray_menu_enter_notify_event(self, widget, event, data = None):
    self.mouse_in_tray_menu = None


def on_tray_menu_leave_notify_event(self, widget, event, data = None):
    self.mouse_in_tray_menu = event.time + 1 # Timeout in 1 sec


def check_hide_popup(self, data = None):
    if self.mouse_in_tray_menu and self.mouse_in_tray_menu < time.time():
        self.tray_menu.hide()
        self.mouse_in_tray_menu = None

    return True # Keep the timer callback running

You don't have to keep the timer running all the time but it is easier and I am also using it for other things. The calls to enter_notify and leave_notify are somewhat erratic so the timer is necessary.

BTW, this is really only necessary in Windows because in Linux you can click elsewhere and the popup will close.

jcoffland