diff --git a/app/solaar.py b/app/solaar.py index 720f3f96..e1f6a201 100644 --- a/app/solaar.py +++ b/app/solaar.py @@ -66,7 +66,6 @@ def _run(args): icon = ui.status_icon.create(window, menu_actions) else: icon = None - window.present() from gi.repository import Gtk, GObject @@ -94,12 +93,12 @@ def _run(args): # callback delivering status events from the receiver/devices to the UI def status_changed(receiver, device=None, alert=status.ALERT.NONE, reason=None): + if alert & status.ALERT.MED: + GObject.idle_add(window.present) if window: GObject.idle_add(ui.main_window.update, window, receiver, device) if icon: GObject.idle_add(ui.status_icon.update, icon, receiver, device) - if alert & status.ALERT.MED: - GObject.idle_add(window.popup, icon) if ui.notify.available: # always notify on receiver updates @@ -109,7 +108,7 @@ def _run(args): if receiver is DUMMY: GObject.timeout_add(3000, check_for_listener) - GObject.timeout_add(0, check_for_listener, True) + GObject.timeout_add(10, check_for_listener, True) Gtk.main() if listener: diff --git a/app/ui/main_window.py b/app/ui/main_window.py index 0d372219..b1654c04 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -278,27 +278,36 @@ def create(title, name, max_devices, systray=False): x, y, _ = Gtk.StatusIcon.position_menu(Gtk.Menu(), trigger) w.move(x, y) w.present() - w.deiconify() return True - def _popup(w, trigger=None): - if not w.get_visible(): - w.toggle_visible(trigger) + def _set_has_systray(w, systray): + if systray != w._has_systray: + w._has_systray = systray + if systray: + if w._delete_event_connection is None or not w.get_skip_taskbar_hint(): + w.set_skip_taskbar_hint(True) + w.set_skip_pager_hint(True) + if w._delete_event_connection: + w.disconnect(w._delete_event_connection) + w._delete_event_connection = w.connect('delete-event', _toggle_visible) + else: + if w._delete_event_connection is None or w.get_skip_taskbar_hint(): + w.set_skip_taskbar_hint(False) + w.set_skip_pager_hint(False) + if w._delete_event_connection: + w.disconnect(w._delete_event_connection) + w._delete_event_connection = w.connect('delete-event', Gtk.main_quit) + w.present() from types import MethodType window.toggle_visible = MethodType(_toggle_visible, window) - window.popup = MethodType(_popup, window) + window.set_has_systray = MethodType(_set_has_systray, window) del MethodType - if systray: - window.set_keep_above(True) - # window.set_decorated(False) - # window.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) - window.set_skip_taskbar_hint(True) - window.set_skip_pager_hint(True) - window.connect('delete-event', _toggle_visible) - else: - window.connect('delete-event', Gtk.main_quit) + window.set_keep_above(True) + window._delete_event_connection = None + window._has_systray = None + window.set_has_systray(systray) return window diff --git a/app/ui/status_icon.py b/app/ui/status_icon.py index e8ef1363..8bdc1219 100644 --- a/app/ui/status_icon.py +++ b/app/ui/status_icon.py @@ -4,7 +4,7 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from gi.repository import Gtk, GdkPixbuf +from gi.repository import Gtk, GObject, GdkPixbuf import ui from logitech.unifying_receiver import status as _status @@ -13,13 +13,15 @@ from logitech.unifying_receiver import status as _status # # +_NO_DEVICES = [None] * 6 + def create(window, menu_actions=None): name = window.get_title() icon = Gtk.StatusIcon() icon.set_title(name) icon.set_name(name) icon.set_from_icon_name(ui.appicon(False)) - icon._devices = {} + icon._devices = list(_NO_DEVICES) icon.set_tooltip_text(name) icon.connect('activate', window.toggle_visible) @@ -37,6 +39,13 @@ def create(window, menu_actions=None): menu.popup(None, None, icon.position_menu, icon, button, time), menu) + # use size-changed to detect if the systray is available or not + def _size_changed(i, size, w): + def _check_systray(i2, w2): + w2.set_has_systray(i2.is_embedded() and i2.get_visible()) + GObject.timeout_add(250, _check_systray, i, w) + icon.connect('size-changed', _size_changed, window) + return icon @@ -71,34 +80,34 @@ def update(icon, receiver, device=None): if device: icon._devices[device.number] = None if device.status is None else device + if not receiver: + icon._devices[:] = _NO_DEVICES + if not icon.is_embedded(): + return lines = [ui.NAME + ': ' + str(receiver.status), ''] - if receiver: - for k in range(1, 1 + receiver.max_devices): - dev = icon._devices.get(k) - if dev is None: - continue + for dev in icon._devices: + if dev is None: + continue - lines.append('' + dev.name + '') + lines.append('' + dev.name + '') - assert hasattr(dev, 'status') and dev.status is not None - p = str(dev.status) - if p: - if not dev.status: - p += ' (inactive)' + assert hasattr(dev, 'status') and dev.status is not None + p = str(dev.status) + if p: + if not dev.status: + p += ' (inactive)' + else: + if dev.status: + p = 'no status' else: - if dev.status: - p = 'no status' - else: - p = '(inactive)' + p = '(inactive)' - lines.append('\t' + p) - lines.append('') + lines.append('\t' + p) + lines.append('') - if battery_status is None and dev.status.get(_status.BATTERY_LEVEL): - battery_status = dev.status - else: - icon._devices.clear() + if battery_status is None and dev.status.get(_status.BATTERY_LEVEL): + battery_status = dev.status icon.set_tooltip_markup('\n'.join(lines).rstrip('\n'))