summaryrefslogtreecommitdiffstats
path: root/esheep.py
diff options
context:
space:
mode:
Diffstat (limited to 'esheep.py')
-rw-r--r--esheep.py64
1 files changed, 58 insertions, 6 deletions
diff --git a/esheep.py b/esheep.py
index 5bf2328..b86fc90 100644
--- a/esheep.py
+++ b/esheep.py
@@ -204,6 +204,9 @@ class WayfireWindows:
self._taskbar: Optional[Tuple[int,int,int,int]] = None
self._lock = threading.Lock()
self._available = False
+ # Unknown until SheepOverlay reports real geometry; keep permissive
+ # (no filtering) until then rather than wrongly excluding everything.
+ self._screen_h = 1_000_000
socket_path = os.environ.get('WAYFIRE_SOCKET', '')
if socket_path and os.path.exists(socket_path):
@@ -222,16 +225,39 @@ class WayfireWindows:
try:
views = sock.list_views()
wins = []
- taskbar = None
+ panel_rects = []
for v in views:
g = v.get('geometry', {})
x, y = g.get('x', 0), g.get('y', 0)
w, h = g.get('width', 0), g.get('height', 0)
role = v.get('role', '')
- # Only toplevel windows count as landing surfaces;
- # skip layer-shell panels/backgrounds (they can hide the sheep)
- if role == 'toplevel' and w > 10 and h > 10:
+ layer = v.get('layer', '')
+ # Toplevel windows count as landing surfaces — but only
+ # if their top edge is actually on the visible screen.
+ # This compositor's wide-viewport layout reports windows
+ # from other workspaces with raw/absolute geometry, so a
+ # window can have x within [0, screenW] while its y sits
+ # off the top of the current monitor entirely; landing a
+ # sheep on such a "floor" puts it above y=0 — invisible.
+ if (role == 'toplevel' and w > 10 and h > 10
+ and 0 <= y <= self._screen_h):
wins.append((x, y, w, h))
+ # Desktop panels/bars (waybar, etc.) anchored to a
+ # top/bottom layer act as the "taskbar" landing surface.
+ # Filter out tall/narrow docks — a taskbar is a wide
+ # horizontal strip, not a sidebar.
+ elif (role == 'desktop-environment' and
+ layer in ('top', 'bottom') and w > h):
+ panel_rects.append((x, y, w, h))
+
+ taskbar = None
+ if panel_rects:
+ px0 = min(r[0] for r in panel_rects)
+ py0 = min(r[1] for r in panel_rects)
+ px1 = max(r[0] + r[2] for r in panel_rects)
+ py1 = max(r[1] + r[3] for r in panel_rects)
+ taskbar = (px0, py0, px1 - px0, py1 - py0)
+
with self._lock:
self._windows = wins
self._taskbar = taskbar
@@ -251,6 +277,9 @@ class WayfireWindows:
with self._lock:
return self._taskbar
+ def set_screen_size(self, screen_h: int):
+ self._screen_h = screen_h
+
# ─────────────────────── Sheep state machine ───────────────────────
class Sheep:
@@ -384,11 +413,16 @@ class Sheep:
# Collect all candidate floors (surfaces the sheep could land on)
all_floors = [(float(screen_h), COND_NONE)]
- # Taskbar (treat as window)
+ # Taskbar (treat as window) — stand on whichever edge faces the
+ # screen interior. A bottom-anchored bar: stand on its top edge
+ # (ty), same as a window. A top-anchored bar (as on this desktop):
+ # standing on its "top" would be above y=0, off-screen — instead
+ # stand just below it, on its bottom edge (ty + th).
if taskbar:
tx, ty, tw, th = taskbar
if tx < self.x + self.tile_w - 4 and tx + tw > self.x + 4:
- all_floors.append((float(ty), COND_TASKBAR))
+ floor_y = (ty + th) if ty <= 2 else ty
+ all_floors.append((float(floor_y), COND_TASKBAR))
# Window tops – only windows that horizontally overlap the sheep
for (wx, wy, ww, wh) in windows:
@@ -738,6 +772,7 @@ class SheepOverlay:
self._flowers: List[Flower] = []
self._eat_countdown = random.uniform(30, 90) # seconds
self._hop_countdown = random.uniform(45, 90) # seconds
+ self._bath_countdown = random.uniform(60, 150) # seconds
self._interact_cooldowns: Dict[Tuple[int,int], float] = {} # ms
self._frozen_sheep: Dict[int, float] = {} # id→remaining ms
@@ -817,6 +852,7 @@ class SheepOverlay:
geo = mon.get_geometry()
self.screen_w = geo.width
self.screen_h = geo.height
+ self.wayfire.set_screen_size(self.screen_h)
print(f"Screen: {self.screen_w}×{self.screen_h}", flush=True)
# Spawn initial sheep
@@ -1023,6 +1059,22 @@ class SheepOverlay:
chosen._init_anim(5)
print("Sheep small hop!", flush=True)
+ # ── bath (batha→bathb→bathc→bathd→rotate1b→walk) ──
+ # Normally only reachable via a ~3% spawn roll; trigger it
+ # periodically too so the sequence is actually seen in practice.
+ self._bath_countdown -= dt / 1000.0
+ if self._bath_countdown <= 0:
+ self._bath_countdown = random.uniform(90, 180)
+ bath_candidates = [s for s in self.sheep_list
+ if s is not self._drag_sheep
+ and s.floor_cond == COND_NONE
+ and s.anim_id in (1, 7, 35, 36, 49, 50)
+ and not any(u.sheep is s for u in self.ufos)]
+ if bath_candidates:
+ chosen = random.choice(bath_candidates)
+ chosen._init_anim(21)
+ print("Sheep is taking a bath!", flush=True)
+
# ── bumps & greetings ──
self._check_interactions(dt)