diff --git a/examples/bar/config.py b/examples/bar/config.py index ed394383..97a1c0ff 100644 --- a/examples/bar/config.py +++ b/examples/bar/config.py @@ -39,6 +39,8 @@ def hyprland_workspace_button(workspace: HyprlandWorkspace) -> widgets.Button: ) if workspace.id == hyprland.active_workspace.id: widget.add_css_class("active") + if workspace.is_urgent: + widget.add_css_class("urgent") return widget @@ -104,8 +106,8 @@ def hyprland_workspaces() -> widgets.EventBox: css_classes=["workspaces"], spacing=5, child=hyprland.bind_many( # bind also to active_workspace to regenerate workspaces list when active workspace changes - ["workspaces", "active_workspace"], - transform=lambda workspaces, active_workspace: [ + ["workspaces", "active_workspace", "urgent_workspaces"], + transform=lambda workspaces, active_workspace, urgent_workspaces: [ workspace_button(i) for i in workspaces ], ), diff --git a/examples/bar/style.scss b/examples/bar/style.scss index 8a7ec747..129c91ef 100644 --- a/examples/bar/style.scss +++ b/examples/bar/style.scss @@ -8,6 +8,7 @@ $bg-light: #261d1e; $fg: #f0dedf; $active: #ffb2bc; $unactive: #d7c1c3; +$urgent: #eb6f92; .bar { padding: 0.4rem 1rem; @@ -54,6 +55,11 @@ $unactive: #d7c1c3; color: $bg; } +.workspace.urgent { + background-color: $urgent; + color: $bg; +} + .tray-item { all: unset; } @@ -97,4 +103,5 @@ popover.menu { } } -} \ No newline at end of file +} + diff --git a/ignis/services/hyprland/service.py b/ignis/services/hyprland/service.py index 4a75faa5..03f2dc2b 100644 --- a/ignis/services/hyprland/service.py +++ b/ignis/services/hyprland/service.py @@ -143,6 +143,20 @@ def workspaces(self) -> list[HyprlandWorkspace]: """ return list(self._workspaces.values()) + @IgnisProperty + def urgent_windows(self) -> list[HyprlandWindow]: + """ + A list of urgent windows. + """ + return [i for i in self._windows.values() if i.is_urgent] + + @IgnisProperty + def urgent_workspaces(self) -> list[HyprlandWorkspace]: + """ + A list of urgent workspaces. + """ + return [i for i in self._workspaces.values() if i.is_urgent] + @IgnisProperty def active_workspace(self) -> HyprlandWorkspace: """ @@ -194,6 +208,8 @@ def get_full_w_addr(addr: str) -> str: value_list = event_value.split(",") match event_type: + case "urgent": + self.__sync_urgent(get_full_w_addr(value_list[0])) case "destroyworkspacev2": self.__destroy_workspace(int(value_list[0])) case "createworkspacev2": @@ -357,12 +373,28 @@ def __sync_main_keyboard(self) -> None: def __sync_active_layout(self, layout: str) -> None: self._main_keyboard.sync({"active_keymap": layout}) + def __sync_urgent(self, urgent_window) -> None: + if urgent_window in self._windows: + self._windows[urgent_window]._urgent = True + self.notify("urgent_windows") + self.notify("urgent_workspaces") + def __sync_active_window(self) -> None: active_window_data = json.loads(self.send_command("j/activewindow")) if active_window_data == {}: active_window_data = HyprlandWindow().data self.active_window.sync(active_window_data) + + active_window_id = active_window_data["address"] + if ( + active_window_id in self._windows + and self._windows[active_window_id]._urgent + ): + self._windows[active_window_id]._urgent = False + self.notify("urgent_windows") + self.notify("urgent_workspaces") + self.notify("active-window") def __open_window(self, address: str) -> None: diff --git a/ignis/services/hyprland/window.py b/ignis/services/hyprland/window.py index de7ff5c2..854e444a 100644 --- a/ignis/services/hyprland/window.py +++ b/ignis/services/hyprland/window.py @@ -43,6 +43,7 @@ def __init__(self): self._swallowing: str = "" self._focus_history_id: int = -1 self._inhibiting_idle: bool = False + self._urgent: bool = False def sync(self, data: dict[str, Any]) -> None: """ @@ -227,3 +228,10 @@ def inhibiting_idle(self) -> bool: The inhibiting idle status. """ return self._inhibiting_idle + + @IgnisProperty + def is_urgent(self) -> bool: + """ + Whether this window is urgent or not + """ + return self._urgent diff --git a/ignis/services/hyprland/workspace.py b/ignis/services/hyprland/workspace.py index 925227e2..7cd85356 100644 --- a/ignis/services/hyprland/workspace.py +++ b/ignis/services/hyprland/workspace.py @@ -1,4 +1,5 @@ from ignis.gobject import IgnisProperty, IgnisSignal, DataGObject +from .window import HyprlandWindow MATCH_DICT = { "monitorID": "monitor_id", @@ -68,6 +69,15 @@ def windows(self) -> int: """ return self._windows + @IgnisProperty + def window_objs(self) -> list[HyprlandWindow]: + """ + All window objects on the workspace (parsed) + """ + return [ + i for i in self.__service._windows.values() if i.workspace_id == self._id + ] + @IgnisProperty def has_fullscreen(self) -> bool: """ @@ -96,6 +106,10 @@ def is_persistent(self) -> bool: """ return self._is_persistent + @IgnisProperty + def is_urgent(self): + return any(i.is_urgent for i in self.window_objs) + def switch_to(self) -> None: """ Switch to this workspace.