2

python: 2.7.5

os: linux, fedora 19

this is a minimum example code to show the problem that i am having, the tray part of the code is excluded cause it is working fine.

run it in a terminal, when the minimize button is press, it enter a show() and hide() loop

i think the easiest way to show it is to make it print a number every it show or hide itself.

the question is: how do i get it to work correctly without it getting stuck in a loop?

from gi.repository import Gtk, Gdk

class Win(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", self.delete_event)
        #something to make it easier to see the loop
        self.num = 0
        self.connect('window-state-event', self.window_state_event_cb)

    def window_state_event_cb(self, widget, event):
       if event.changed_mask & Gdk.WindowState.ICONIFIED:
          if event.new_window_state & Gdk.WindowState.ICONIFIED:
             self.hide()
             print 'Window was minimized!'
          else:
             self.show()
             print 'Window was unminimized!'
          self.num += 1
          print(self.num)

    def delete_event(self,window,event):
        Gtk.main_quit()

if __name__=="__main__":
    win = Win()
    win.show_all()
    Gtk.main()

code pieced together from http://faq.pygtk.org/index.py?req=edit&file=faq10.022.htp

freeforall tousez
  • 836
  • 10
  • 26

1 Answers1

3

I had the same issue and this works for me.

def on_windowStateEvent(self, widget, event):
  if (event.changed_mask & Gdk.WindowState.ICONIFIED):
    if (event.new_window_state & Gdk.WindowState.ICONIFIED):
      # minimize visible widow. We hide the window to remove it
      # from the active tasks windows, a click the tray icon will
      # bring it back
      self.window.hide()
    else:
      # don't do anything here. The call from hide() above causes a 
      # new event that ends here. And calling show() now will result
      # in a loop
      pass

def statusIcon_activate(self, statusIcon):
  # restore the hidden window on a click on the tray icon
  self.window.deiconify()
  self.window.present() # present the window on the active desktop

...
self.window = Gtk.Window()
self.window.connect("window-state-event", self.on_windowStateEvent)
....
self.statusIcon = Gtk.StatusIcon()
self.statusIcon.connect("activate", self.statusIcon_activate)
...

And there is the short form:

def isEventIconify(event):
  return (event.changed_mask
          & event.new_window_state
          & Gdk.WindowState.ICONIFIED)

def on_windowStateEvent(self, widget, event):
  if isEventIconify(event):
    self.window.hide()
Axel Heider
  • 557
  • 4
  • 14
  • The nested `if` is redundant. You just need to `and` the conditions together. Given you're already doing bit twiddling, you might be able to just `&` all three together (`event.changed_mask`, `event.new_window_state`, and `Gdk.WindowState.ICONIFIED`), but I'm not 100% sure. – jpmc26 Mar 27 '16 at 00:42
  • True, but this was meant as a very verbose example based on the code above and the code references in the PyGTK FAQ. It still keeps the places where to add more code given one wants to make the "minimize to tray" feature configurable. – Axel Heider Mar 27 '16 at 00:48