Fix window visibility

This fixes the FPDB main window visibility with window managers that use
workspaces instead of virtual desktop(s). On such a system the
application receives WINDOW_STATE_ICONIFIED event when the workspace is
switched. This hides the window.

It wouldn't be too big a problem if the window wouldn't occasionally get
stuck in a "hide-me-loop", where any attempt to unhide/present the
window again triggers the hide routine. The two state events, _ICONIFIED
and _WITHDRAWN are not the same or even mutually exclusive. As such the
old event mask test simply did not cover all the possibilities.

Also, the property 'visible' does not necessarily match reality. It can
be set to true for iconified windows, and false to a visible window. So
a better solution is to not rely on the property, but just track the
wanted visibility state in our own code.

After this simple refactoring, the application window finally seems to
behave properly. [Also, widget.present() automatically calls .show(), so
we can kill one redundant operation.]
This commit is contained in:
Mika Bostrom 2010-08-21 14:24:34 +03:00
parent 48e0cbe8cd
commit bf2eaa772c

View File

@ -1093,6 +1093,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
self.status_bar = None self.status_bar = None
self.quitting = False self.quitting = False
self.visible = False
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("delete_event", self.delete_event) self.window.connect("delete_event", self.delete_event)
self.window.connect("destroy", self.destroy) self.window.connect("destroy", self.destroy)
@ -1130,6 +1131,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
self.tab_main_help(None, None) self.tab_main_help(None, None)
self.window.show() self.window.show()
self.visible = True # Flip on
self.load_profile(create_db = True) self.load_profile(create_db = True)
if not options.errorsToConsole: if not options.errorsToConsole:
@ -1165,21 +1167,31 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
self.window.connect('window-state-event', self.window_state_event_cb) self.window.connect('window-state-event', self.window_state_event_cb)
sys.stderr.write(_("fpdb starting ...")) sys.stderr.write(_("fpdb starting ..."))
def window_state_event_cb(self, window, event):
if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
# -20 = GWL_EXSTYLE can't find it in the pywin32 libs
#bits = win32api.GetWindowLong(self.window.window.handle, -20)
#bits = bits ^ (win32con.WS_EX_TOOLWINDOW | win32con.WS_EX_APPWINDOW)
#win32api.SetWindowLong(self.window.window.handle, -20, bits) def __iconify(self):
self.visible = False
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
self.window.hide()
self.window.set_skip_taskbar_hint(True) self.window.set_skip_taskbar_hint(True)
self.window.set_skip_pager_hint(True) self.window.set_skip_pager_hind(True)
else:
def __deiconify(self):
self.visible = True
self.window.set_skip_taskbar_hint(False) self.window.set_skip_taskbar_hint(False)
self.window.set_skip_pager_hint(False) self.window.set_skip_pager_hind(False)
def window_state_event_cb(self, window, event):
# Deal with iconification first
if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
self.__iconify()
else:
self.__deiconify()
if not event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN:
return True
# And then the tray icon click
if event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN:
self.__iconify()
else:
self.__deiconify()
# Tell GTK not to propagate this signal any further # Tell GTK not to propagate this signal any further
return True return True
@ -1197,11 +1209,9 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
def statusicon_activate(self, widget, data = None): def statusicon_activate(self, widget, data = None):
# Let's allow the tray icon to toggle window visibility, the way # Let's allow the tray icon to toggle window visibility, the way
# most other apps work # most other apps work
shown = self.window.get_property('visible') if self.visible:
if shown:
self.window.hide() self.window.hide()
else: else:
self.window.show()
self.window.present() self.window.present()
def info_box(self, str1, str2): def info_box(self, str1, str2):