147 lines
5.2 KiB
Python
147 lines
5.2 KiB
Python
import subprocess
|
|
import json
|
|
|
|
import config.data as data
|
|
|
|
def get_current_workspace():
|
|
"""
|
|
Get the current workspace ID using hyprctl.
|
|
"""
|
|
try:
|
|
result = subprocess.run(
|
|
["hyprctl", "activeworkspace"],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
# Assume the output similar to: "ID <number>"
|
|
# Extracting the number from the output
|
|
parts = result.stdout.split()
|
|
for i, part in enumerate(parts):
|
|
if part == "ID" and i + 1 < len(parts):
|
|
return int(parts[i+1])
|
|
except Exception as e:
|
|
print(f"Error getting current workspace: {e}")
|
|
return -1
|
|
|
|
def get_screen_dimensions():
|
|
"""
|
|
Get screen dimensions from hyprctl.
|
|
|
|
Returns:
|
|
tuple: (width, height) of the monitor containing the current workspace
|
|
"""
|
|
try:
|
|
# Get current workspace
|
|
workspace_id = get_current_workspace()
|
|
|
|
# Get monitor information
|
|
result = subprocess.run(
|
|
["hyprctl", "-j", "monitors"],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
monitors = json.loads(result.stdout)
|
|
|
|
# Find the monitor containing our workspace
|
|
for monitor in monitors:
|
|
if monitor.get("activeWorkspace", {}).get("id") == workspace_id:
|
|
return monitor.get("width", data.CURRENT_WIDTH), monitor.get("height", data.CURRENT_HEIGHT)
|
|
|
|
# Fallback to first monitor
|
|
if monitors:
|
|
return monitors[0].get("width", data.CURRENT_WIDTH), monitors[0].get("height", data.CURRENT_HEIGHT)
|
|
except Exception as e:
|
|
print(f"Error getting screen dimensions: {e}")
|
|
|
|
# Default fallback values
|
|
return data.CURRENT_WIDTH, data.CURRENT_HEIGHT
|
|
|
|
def check_occlusion(occlusion_region, workspace=None):
|
|
"""
|
|
Check if a region is occupied by any window on a given workspace.
|
|
|
|
Parameters:
|
|
occlusion_region: Can be one of:
|
|
- tuple (side, size): where side is "top", "bottom", "left", or "right"
|
|
and size is the pixel width of the region
|
|
- tuple (x, y, width, height): The full region coordinates (legacy format)
|
|
workspace (int, optional): The workspace ID to check. If None, the current workspace is used.
|
|
|
|
Returns:
|
|
bool: True if any window overlaps with the occlusion region, False otherwise.
|
|
"""
|
|
if workspace is None:
|
|
workspace = get_current_workspace()
|
|
|
|
# Handle simplified side-based format
|
|
if isinstance(occlusion_region, tuple) and len(occlusion_region) == 2:
|
|
side, size = occlusion_region
|
|
if isinstance(side, str):
|
|
# Convert side-based format to coordinates
|
|
screen_width, screen_height = get_screen_dimensions()
|
|
|
|
if side.lower() == "bottom":
|
|
occlusion_region = (0, screen_height - size, screen_width, size)
|
|
elif side.lower() == "top":
|
|
occlusion_region = (0, 0, screen_width, size)
|
|
elif side.lower() == "left":
|
|
occlusion_region = (0, 0, size, screen_height)
|
|
elif side.lower() == "right":
|
|
occlusion_region = (screen_width - size, 0, size, screen_height)
|
|
|
|
# Ensure occlusion_region is in the correct format (x, y, width, height)
|
|
if not isinstance(occlusion_region, tuple) or len(occlusion_region) != 4:
|
|
print(f"Invalid occlusion region format: {occlusion_region}")
|
|
return False
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
["hyprctl", "-j", "clients"],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
clients = json.loads(result.stdout)
|
|
except Exception as e:
|
|
print(f"Error retrieving client windows: {e}")
|
|
return False
|
|
|
|
occ_x, occ_y, occ_width, occ_height = occlusion_region
|
|
occ_x2 = occ_x + occ_width
|
|
occ_y2 = occ_y + occ_height
|
|
|
|
# Get screen dimensions for fullscreen check
|
|
screen_width, screen_height = get_screen_dimensions()
|
|
|
|
for client in clients:
|
|
# Check if client is mapped
|
|
if not client.get("mapped", False):
|
|
continue
|
|
|
|
# Ensure client has proper workspace information and matches the workspace
|
|
client_workspace = client.get("workspace", {})
|
|
if client_workspace.get("id") != workspace:
|
|
continue
|
|
|
|
# Ensure client has position and size info
|
|
position = client.get("at")
|
|
size = client.get("size")
|
|
if not position or not size:
|
|
continue
|
|
|
|
x, y = position
|
|
width, height = size
|
|
win_x1, win_y1 = x, y
|
|
win_x2, win_y2 = x + width, y + height
|
|
|
|
# Check for fullscreen windows (size matches screen and positioned at 0,0)
|
|
if (width, height) == (screen_width, screen_height) and (x, y) == (0, 0):
|
|
# For fullscreen windows, check if occlusion region is the top area
|
|
if occ_y == 0 and occ_height > 0: # Top region
|
|
return True # Consider fullscreen as occluding the top
|
|
|
|
# Check for intersection between the window and occlusion region
|
|
if not (win_x2 <= occ_x or win_x1 >= occ_x2 or win_y2 <= occ_y or win_y1 >= occ_y2):
|
|
return True # Occlusion region is occupied
|
|
|
|
return False # No window overlaps the occlusion region
|