Source code for qtile_expanded.extensions.base_popup
"""
Base Popup class for Qtile Expanded.
This module provides a base class for all popups and a registry to track
all open popups, enabling external control (e.g., via gestures or keybindings).
Features:
- BasePopup: Base class for all popup types
- PopupRegistry: Tracks all open popups
- close_all_popups(): Close all open popups
- is_popup_open(): Check if any popup is open
"""
from libqtile.popup import Popup
from libqtile.log_utils import logger
[docs]
class PopupRegistry:
"""
Registry for tracking all open popups.
This singleton class maintains a list of all open popups, allowing
external code to check if popups are open and close them programmatically.
Usage:
from qtile_expanded.extensions.base_popup import PopupRegistry
# Check if any popup is open
if PopupRegistry.is_popup_open():
print("A popup is open")
# Close all popups
PopupRegistry.close_all_popups()
# Get list of open popups
open_popups = PopupRegistry.get_open_popups()
"""
_instances: list = []
[docs]
@classmethod
def register(cls, popup) -> None:
"""Register a popup as open."""
if popup not in cls._instances:
cls._instances.append(popup)
logger.debug(f"PopupRegistry: Registered popup {popup}")
[docs]
@classmethod
def unregister(cls, popup) -> None:
"""Unregister a popup when it's closed."""
if popup in cls._instances:
cls._instances.remove(popup)
logger.debug(f"PopupRegistry: Unregistered popup {popup}")
[docs]
@classmethod
def get_open_popups(cls) -> list:
"""Get list of all open popups."""
return cls._instances.copy()
[docs]
@classmethod
def is_popup_open(cls) -> bool:
"""Check if any popup is currently open."""
return len(cls._instances) > 0
[docs]
@classmethod
def close_all_popups(cls) -> int:
"""
Close all open popups.
Returns:
Number of popups closed
"""
count = 0
for popup in cls._instances[:]:
try:
if hasattr(popup, 'win') and hasattr(popup.win, 'visible') and popup.win.visible:
popup.hide()
count += 1
cls.unregister(popup)
except Exception as e:
logger.warning(f"PopupRegistry: Error closing popup: {e}")
logger.debug(f"PopupRegistry: Closed {count} popups")
return count
[docs]
@classmethod
def close_popup(cls, popup) -> bool:
"""
Close a specific popup if it's open.
Args:
popup: The popup instance to close
Returns:
True if the popup was open and closed, False otherwise
"""
if popup in cls._instances:
try:
if hasattr(popup, 'win') and hasattr(popup.win, 'visible') and popup.win.visible:
popup.hide()
cls.unregister(popup)
return True
except Exception as e:
logger.warning(f"PopupRegistry: Error closing popup: {e}")
return False
[docs]
class BasePopup(Popup):
"""
Base class for all Qtile Expanded popups.
This class extends Qtile's Popup with:
- Automatic registration in PopupRegistry when shown
- Automatic unregistration when hidden
- Support for external close commands (gestures, keybindings)
All popup classes should inherit from this class instead of
directly from libqtile.popup.Popup.
Usage:
from qtile_expanded.extensions.base_popup import BasePopup
class MyPopup(BasePopup):
def __init__(self, qtile, **config):
super().__init__(qtile, **config)
# Your initialization
"""
[docs]
def __init__(self, qtile, **config):
"""Initialize the base popup."""
super().__init__(qtile, **config)
self._registered = False
# Override hide to unregister when closed
original_hide = self.hide
def hide_with_unregister():
original_hide()
self._unregister()
self.hide = hide_with_unregister
[docs]
def show(self, *args, **kwargs):
"""Show the popup and register it."""
super().show(*args, **kwargs)
self._register()
def _register(self) -> None:
"""Register this popup in the registry."""
PopupRegistry.register(self)
self._registered = True
def _unregister(self) -> None:
"""Unregister this popup from the registry."""
if self._registered:
PopupRegistry.unregister(self)
self._registered = False
[docs]
@classmethod
def close_all(cls) -> int:
"""
Close all popups of this type.
Returns:
Number of popups closed
"""
return PopupRegistry.close_all_popups()
[docs]
@classmethod
def is_any_open(cls) -> bool:
"""Check if any popup is open."""
return PopupRegistry.is_popup_open()
[docs]
def close_all_popups() -> int:
"""
Close all open popups.
This function can be called from anywhere (e.g., gesture handlers,
keybindings) to close all open popups.
Returns:
Number of popups closed
Example:
from qtile_expanded.extensions.base_popup import close_all_popups
# In your Qtile config
def close_popups(qtile):
count = close_all_popups()
if count > 0:
print(f"Closed {count} popups")
keys = [
Key(["mod1"], "Escape", lazy.function(close_popups)),
]
"""
return PopupRegistry.close_all_popups()
[docs]
def is_popup_open() -> bool:
"""
Check if any popup is currently open.
Returns:
True if at least one popup is open, False otherwise
Example:
from qtile_expanded.extensions.base_popup import is_popup_open
if is_popup_open():
print("There is a popup open")
"""
return PopupRegistry.is_popup_open()
[docs]
def get_open_popups() -> list:
"""
Get list of all currently open popups.
Returns:
List of open popup instances
"""
return PopupRegistry.get_open_popups()