urgent tags

This commit is contained in:
Makesesama 2025-05-05 09:31:17 +02:00
parent 0966c1ce70
commit 736e1a47c9
3 changed files with 78 additions and 4 deletions

View File

@ -73,12 +73,21 @@ button {
font-size: 0px;
}
#workspaces>button:hover {
#workspaces button.hover {
background-color: var(--ws-hover);
}
#workspaces>button.urgent {
#workspaces button.urgent {
background-color: var(--ws-urgent);
color: var(--foreground);
font-weight: bold;
animation: urgent-blink 1s infinite;
}
@keyframes urgent-blink {
0% { opacity: 1.0; }
50% { opacity: 0.5; }
100% { opacity: 1.0; }
}
#workspaces>button.empty {

View File

@ -10,7 +10,7 @@ from fabric.utils.helpers import idle_add
# Import pywayland components - ensure these imports are correct
from pywayland.client import Display
from pywayland.protocol.wayland import WlOutput, WlRegistry, WlSeat
from pywayland.protocol.wayland import WlOutput, WlSeat
from .generated.river_status_unstable_v1 import ZriverStatusManagerV1
@ -23,6 +23,7 @@ class OutputInfo:
status: Any = None # ZriverOutputStatusV1
tags_view: List[int] = field(default_factory=list)
tags_focused: List[int] = field(default_factory=list)
tags_urgent: List[int] = field(default_factory=list)
@dataclass(frozen=True)
@ -190,11 +191,23 @@ class River(Service):
return handler
def make_urgent_tags_handler(output_id):
def handler(_, tags):
decoded = self._decode_bitfields(tags)
state["outputs"][output_id].tags_urgent = decoded
logger.debug(
f"[RiverService] Output {output_id} urgent tags: {decoded}"
)
idle_add(lambda: self._emit_urgent_tags(output_id, decoded))
return handler
# Bind output status listeners
for name, info in list(state["outputs"].items()):
status = state["river_status_mgr"].get_river_output_status(info.output)
status.dispatcher["view_tags"] = make_view_tags_handler(name)
status.dispatcher["focused_tags"] = make_focused_tags_handler(name)
status.dispatcher["urgent_tags"] = make_urgent_tags_handler(name)
info.status = status
logger.info(f"[RiverService] Set up status for output {name}")
@ -251,6 +264,13 @@ class River(Service):
self.notify("active-window")
return False # Don't repeat
def _emit_urgent_tags(self, output_id, tags):
"""Emit urgent_tags events (called on main thread)"""
event = RiverEvent("urgent_tags", tags, output_id)
self.emit("event::urgent_tags", event)
self.emit(f"event::urgent_tags::{output_id}", tags)
return False # Don't repeat
@staticmethod
def _decode_bitfields(bitfields) -> List[int]:
"""Decode River's tag bitfields into a list of tag indices"""

View File

@ -43,11 +43,36 @@ class RiverWorkspaceButton(Button):
self._empty = value
(self.remove_style_class if not value else self.add_style_class)("empty")
@Property(bool, "read-write", default_value=False)
def urgent(self) -> bool:
return self._urgent
@urgent.setter
def urgent(self, value: bool):
self._urgent = value
self._update_style()
def __init__(self, id: int, label: str = None, **kwargs):
super().__init__(label or str(id), **kwargs)
self._id = id
self._active = False
self._empty = True
self._urgent = False
def _update_style(self):
"""Update button styles based on states"""
# Remove all state-related styles first
self.remove_style_class("active")
self.remove_style_class("empty")
self.remove_style_class("urgent")
# Then apply current states
if self._active:
self.add_style_class("active")
if self._empty:
self.add_style_class("empty")
if self._urgent:
self.add_style_class("urgent")
class RiverWorkspaces(EventBox):
@ -71,6 +96,7 @@ class RiverWorkspaces(EventBox):
# Connect to service events
self.service.connect("event::focused_tags", self.on_focus_change_general)
self.service.connect("event::view_tags", self.on_view_change_general)
self.service.connect("event::urgent_tags", self.on_urgent_change_general)
self.service.connect("event::output_removed", self.on_output_removed)
# Initial setup when service is ready
@ -100,14 +126,16 @@ class RiverWorkspaces(EventBox):
# Access fields directly on the OutputInfo dataclass
focused_tags = output_info.tags_focused
view_tags = output_info.tags_view
urgent_tags = output_info.tags_urgent
logger.debug(
f"[RiverWorkspaces] Initial state - focused: {focused_tags}, view: {view_tags}"
f"[RiverWorkspaces] Initial state - focused: {focused_tags}, view: {view_tags}, urgent: {urgent_tags}"
)
for i, btn in self._buttons.items():
btn.active = i in focused_tags
btn.empty = i not in view_tags
btn.urgent = i in urgent_tags
def on_focus_change(self, _, tags):
"""Handle focused tags change for our specific output"""
@ -143,6 +171,23 @@ class RiverWorkspaces(EventBox):
)
self.on_view_change(_, event.data)
def on_urgent_change(self, _, tags):
"""Handle urgent tags change for our specific output"""
logger.debug(
f"[RiverWorkspaces] Urgent change on output {self.output_id}: {tags}"
)
for i, btn in self._buttons.items():
btn.urgent = i in tags
def on_urgent_change_general(self, _, event):
"""Handle general urgent tags event"""
# Only handle event if it's for our output
if event.output_id == self.output_id:
logger.debug(
f"[RiverWorkspaces] General urgent change for output {self.output_id}"
)
self.on_urgent_change(_, event.data)
def on_output_removed(self, _, event):
"""Handle output removal"""
removed_id = event.data[0]