Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.venv
.idea
__pycache__
WayKey.egg-info
dist
3 changes: 3 additions & 0 deletions WayKey/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .library.commands import click, press, release, mouse_move, get_devices, load_device, unload_device

__all__ = ["click", "press", "release", "mouse_move", "get_devices", "load_device", "unload_device"]
4 changes: 2 additions & 2 deletions WayKey/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def load_device(device_id: str) -> None:
"""
response = send_command({
"type": "load_device",
"id": device_id
"device_id": device_id
})
if response.get("status") == "success":
print(f"Device {device_id} loaded successfully.")
Expand All @@ -115,7 +115,7 @@ def unload_device(device_id: str) -> None:
"""
response = send_command({
"type": "unload_device",
"id": device_id
"device_id": device_id
})
if response.get("status") == "success":
print(f"Device {device_id} unloaded successfully.")
Expand Down
4 changes: 2 additions & 2 deletions WayKey/daemon/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def get_devices() -> dict:
return {"status": "success", "devices": devices}

def load_device(command: dict) -> dict:
new_id = command.get("id", None)
new_id = command.get("device_id", None)
if not new_id:
return {"status": "error", "message": "Device ID is required"}
device_path = get_path_from_id(new_id)
Expand All @@ -58,7 +58,7 @@ def load_device(command: dict) -> dict:
return {"status": "success", "message": f"Device {device_id} loaded"}

def unload_device(command: dict) -> dict:
device_id = command.get("id", None)
device_id = command.get("device_id", None)
if not is_id_valid(device_id):
return {"status": "error", "message": f"Invalid device ID: {device_id}"}
if device_id not in input_devices:
Expand Down
114 changes: 114 additions & 0 deletions WayKey/library/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
from evdev import ecodes as e
import socket
import json

SOCKET_PATH = "/tmp/waykeyd.sock"

def _send_command(command: dict) -> dict:
"""
Send a command to the daemon and get the response
"""
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
client.connect(SOCKET_PATH)
client.sendall(json.dumps(command).encode('utf-8'))
response = client.recv(4096).decode('utf-8')
return json.loads(response)
finally:
client.close()

def _convert_code(code: str) -> int or None:
"""
Convert a key code from string to integer
"""
for key, value in e.keys.items():
if isinstance(value, tuple):
for v in value:
if v == code:
return key
else:
if value == code:
return key
return None

def press(code: str | int, device_id: str = "default_device") -> dict:
"""
Press a key
"""
if not isinstance(code, int):
code = _convert_code(code)
if code is None:
raise ValueError(f"Invalid key code: {code}")
return _send_command({
"type": "press",
"code": code,
"device_id": device_id
})

def release(code: str | int, device_id: str = "default_device") -> dict:
"""
Release a key
"""
if not isinstance(code, int):
code = _convert_code(code)
if code is None:
raise ValueError(f"Invalid key code: {code}")
return _send_command({
"type": "release",
"code": code,
"device_id": device_id
})

def click(code: str | int, device_id: str = "default_device", delay: int = 0) -> dict:
"""
Click a key
"""
if not isinstance(code, int):
code = _convert_code(code)
if code is None:
raise ValueError(f"Invalid key code: {code}")
return _send_command({
"type": "click",
"code": code,
"device_id": device_id,
"delay": delay
})

def mouse_move(x: int, y: int, w: int = 0, absolute: bool = False, device_id: str = "default_device") -> dict:
"""
Move the mouse cursor
"""
return _send_command({
"type": "mouse_move",
"x": x,
"y": y,
"w": w,
"absolute": absolute,
"device_id": device_id
})

def get_devices() -> dict:
"""
Get a list of all devices
"""
return _send_command({
"type": "get_devices"
})

def load_device(device_id: str = "default_device") -> dict:
"""
Load a device by its ID
"""
return _send_command({
"type": "load_device",
"device_id": device_id
})

def unload_device(device_id: str = "default_device") -> dict:
"""
Unload a device by its ID
"""
return _send_command({
"type": "unload_device",
"device_id": device_id
})
18 changes: 15 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[project]
name = "WayKey"
version = "0.1.0"
readme = "README.md"
description = "Wayland automation"
requires-python = ">=3.13"
Expand All @@ -16,11 +17,22 @@ classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: End Users/Desktop",
]
dependencies = [
"evdev>=1.9.2",
"screeninfo>=0.8.1",
]
[project.urls]
Source = "https://github.com/Nmstr/WayKey"
Issues = "https://github.com/Nmstr/WayKey/issues"

dependencies = [
"evdev>=1.9.2",
"screeninfo>=0.8.1",
[build-system]
requires = ["uv_build>=0.7.20,<0.8.0"]
build-backend = "uv_build"

[tool.uv.build-backend]
module-root = ""
module-name = "WayKey"
source-exclude = [
"daemon",
"cli"
]