From 910a780ad2bba77a16134966cfeaa9205512c93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moses=20Palm=C3=A9r?= Date: Mon, 11 Oct 2021 20:06:12 +0200 Subject: [PATCH 1/4] Enforced line length --- lib/pystray/_base.py | 18 +++++++++--------- lib/pystray/_darwin.py | 4 ++-- lib/pystray/_gtk.py | 6 ++++-- lib/pystray/_util/win32.py | 3 ++- lib/pystray/_win32.py | 16 ++++++++-------- lib/pystray/_xorg.py | 11 +++++++---- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/pystray/_base.py b/lib/pystray/_base.py index 8b8c754..ed80507 100644 --- a/lib/pystray/_base.py +++ b/lib/pystray/_base.py @@ -176,9 +176,9 @@ def run(self, setup=None): thread once the loop has started. It is passed the icon as its sole argument. - If not specified, a simple setup function setting :attr:`visible` to - ``True`` is used. If you specify a custom setup function, you must - explicitly set this attribute. + If not specified, a simple setup function setting :attr:`visible` + to ``True`` is used. If you specify a custom setup function, you + must explicitly set this attribute. """ def setup_handler(): self.__queue.get() @@ -384,8 +384,8 @@ def checked(self): """Whether this item is checked. This can be either ``True``, which implies that the item is checkable - and checked, ``False``, which implies that the item is checkable but not - checked, and ``None`` for uncheckable items. + and checked, ``False``, which implies that the item is checkable but + not checked, and ``None`` for uncheckable items. Depending on platform, uncheckable items may be rendered differently from unchecked items. @@ -396,8 +396,8 @@ def checked(self): def radio(self): """Whether this item is a radio button. - This is only used for checkable items. It is always set to ``False`` for - uncheckable items. + This is only used for checkable items. It is always set to ``False`` + for uncheckable items. """ if self.checked is not None: return self._radio(self) @@ -442,8 +442,8 @@ def _assert_action(self, action): less than the expected number of arguments, a wrapper will be returned. - :raises ValueError: if ``action`` requires more than the expected number - of arguments + :raises ValueError: if ``action`` requires more than the expected + number of arguments :return: a callable """ diff --git a/lib/pystray/_darwin.py b/lib/pystray/_darwin.py index bf2358a..d31b6b4 100644 --- a/lib/pystray/_darwin.py +++ b/lib/pystray/_darwin.py @@ -202,8 +202,8 @@ def _create_menu(self, descriptors, callbacks): return nsmenu def _create_menu_item(self, descriptor, callbacks): - """Creates a :class:`AppKit.NSMenuItem` from a :class:`pystray.MenuItem` - instance. + """Creates a :class:`AppKit.NSMenuItem` from a + :class:`pystray.MenuItem` instance. :param descriptor: The menu item descriptor. diff --git a/lib/pystray/_gtk.py b/lib/pystray/_gtk.py index 14c5084..d6aeae0 100644 --- a/lib/pystray/_gtk.py +++ b/lib/pystray/_gtk.py @@ -27,8 +27,10 @@ def __init__(self, *args, **kwargs): super(Icon, self).__init__(*args, **kwargs) self._status_icon = Gtk.StatusIcon.new() - self._status_icon.connect('activate', self._on_status_icon_activate) - self._status_icon.connect('popup-menu', self._on_status_icon_popup_menu) + self._status_icon.connect( + 'activate', self._on_status_icon_activate) + self._status_icon.connect( + 'popup-menu', self._on_status_icon_popup_menu) if self.icon: self._update_icon() diff --git a/lib/pystray/_util/win32.py b/lib/pystray/_util/win32.py index de3e03d..c6c84fa 100644 --- a/lib/pystray/_util/win32.py +++ b/lib/pystray/_util/win32.py @@ -347,7 +347,8 @@ def _err(result, func, arguments): ChangeWindowMessageFilterEx.errcheck = _err except KeyError: - def ChangeWindowMessageFilterEx(hWnd, message, action, pCHangeFilterStruct): + def ChangeWindowMessageFilterEx( + hWnd, message, action, pCHangeFilterStruct): """A dummy implementation of ``ChangeWindowMessageFilterEx`` always returning ``TRUE``. diff --git a/lib/pystray/_win32.py b/lib/pystray/_win32.py index 23d039c..3847bdc 100644 --- a/lib/pystray/_win32.py +++ b/lib/pystray/_win32.py @@ -238,22 +238,22 @@ def _create_window(self, atom): win32.GetModuleHandle(None), None) - # On Vista+, we must explicitly opt-in to receive WM_TASKBARCREATED when - # running with escalated privileges + # On Vista+, we must explicitly opt-in to receive WM_TASKBARCREATED + # when running with escalated privileges win32.ChangeWindowMessageFilterEx( hwnd, win32.WM_TASKBARCREATED, win32.MSGFLT_ALLOW, None) return hwnd def _create_menu(self, descriptors, callbacks): - """Creates a :class:`ctypes.wintypes.HMENU` from a :class:`pystray.Menu` - instance. + """Creates a :class:`ctypes.wintypes.HMENU` from a + :class:`pystray.Menu` instance. :param descriptors: The menu descriptors. If this is falsy, ``None`` is returned. :param callbacks: A list to which a callback is appended for every menu - item created. The menu item IDs correspond to the items in this list - plus one. + item created. The menu item IDs correspond to the items in this + list plus one. :return: a menu """ @@ -279,8 +279,8 @@ def _create_menu_item(self, descriptor, callbacks): :param descriptor: The menu item descriptor. :param callbacks: A list to which a callback is appended for every menu - item created. The menu item IDs correspond to the items in this list - plus one. + item created. The menu item IDs correspond to the items in this + list plus one. :return: a :class:`pystray._util.win32.MENUITEMINFO` """ diff --git a/lib/pystray/_xorg.py b/lib/pystray/_xorg.py index 368ac7b..67fcc75 100644 --- a/lib/pystray/_xorg.py +++ b/lib/pystray/_xorg.py @@ -142,8 +142,8 @@ def _show(self): try: self._assert_docked() except AssertionError: - # There is no systray selection owner, so we cannot dock; ignore and - # dock later + # There is no systray selection owner, so we cannot dock; ignore + # and dock later self._log.error( 'Failed to dock icon', exc_info=True) @@ -305,7 +305,8 @@ def on_client_message(event): # Create the atoms and a mapping from atom to actual implementation atoms = [ - self._display.intern_atom('_PYSTRAY_%s' % original.__name__.upper()) + self._display.intern_atom( + '_PYSTRAY_%s' % original.__name__.upper()) for original in args] handlers = { atom: wrapper(original) @@ -333,10 +334,12 @@ def _create_window(self): -1, -1, 1, 1, 0, screen.root_depth, event_mask=Xlib.X.ExposureMask | Xlib.X.StructureNotifyMask, window_class=Xlib.X.InputOutput) + flags = ( + Xlib.Xutil.PPosition | Xlib.Xutil.PSize | Xlib.Xutil.PMinSize) window.set_wm_class('%sSystemTrayIcon' % self.name, self.name) window.set_wm_name(self.title) window.set_wm_normal_hints( - flags=(Xlib.Xutil.PPosition | Xlib.Xutil.PSize | Xlib.Xutil.PMinSize), + flags=flags, min_width=24, min_height=24) From c535c68d13f4219385d09c8267da9dc60eec2016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moses=20Palm=C3=A9r?= Date: Mon, 11 Oct 2021 20:06:23 +0200 Subject: [PATCH 2/4] Corrected spelling --- lib/pystray/_win32.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pystray/_win32.py b/lib/pystray/_win32.py index 3847bdc..d41b966 100644 --- a/lib/pystray/_win32.py +++ b/lib/pystray/_win32.py @@ -265,7 +265,7 @@ def _create_menu(self, descriptors, callbacks): hmenu = win32.CreatePopupMenu() for i, descriptor in enumerate(descriptors): # Append the callbacks before creating the menu items to ensure - # that the first item get the ID 1 + # that the first item gets the ID 1 callbacks.append(self._handler(descriptor)) menu_item = self._create_menu_item(descriptor, callbacks) win32.InsertMenuItem(hmenu, i, True, ctypes.byref(menu_item)) From ff62ccebf10cf811952f17f45653f2a0ab41c3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moses=20Palm=C3=A9r?= Date: Mon, 11 Oct 2021 20:07:53 +0200 Subject: [PATCH 3/4] Do not fail catching SIGINT in non-main thread --- lib/pystray/_util/gtk.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pystray/_util/gtk.py b/lib/pystray/_util/gtk.py index 3d21dbc..133493a 100644 --- a/lib/pystray/_util/gtk.py +++ b/lib/pystray/_util/gtk.py @@ -64,8 +64,13 @@ def _run(self): self._notifier = notify_dbus.Notifier() self._mark_ready() - # Make sure that we do not inhibit ctrl+c - signal.signal(signal.SIGINT, signal.SIG_DFL) + # Make sure that we do not inhibit ctrl+c; this is only possible from + # the main thread + try: + signal.signal(signal.SIGINT, signal.SIG_DFL) + except ValueError: + pass + try: self._loop.run() except: From 588988eeaa1049d4ceca3f5e56a7282cd043dd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moses=20Palm=C3=A9r?= Date: Mon, 11 Oct 2021 20:15:20 +0200 Subject: [PATCH 4/4] Always mark icon ready in _mark_ready --- lib/pystray/_base.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/pystray/_base.py b/lib/pystray/_base.py index ed80507..69d3926 100644 --- a/lib/pystray/_base.py +++ b/lib/pystray/_base.py @@ -247,8 +247,10 @@ def _mark_ready(self): is called. """ self._running = True - self.update_menu() - self.__queue.put(True) + try: + self.update_menu() + finally: + self.__queue.put(True) def _handler(self, callback): """Generates a callback handler.