Created
December 20, 2025 18:37
-
-
Save tych0/b7263cb5d6c8e42cce902fb2132f3c89 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Monitor screensaver events using the MIT-SCREEN-SAVER extension. | |
| Uses an event-driven approach with SelectInput to receive notifications. | |
| """ | |
| import xcffib | |
| import xcffib.xproto | |
| import xcffib.screensaver | |
| import sys | |
| import select | |
| def monitor_screensaver_events(): | |
| """ | |
| Monitor screensaver events using an event loop. | |
| Receives NotifyEvents when the screensaver state changes. | |
| """ | |
| # Connect to X server | |
| conn = xcffib.connect() | |
| # Get the screensaver extension | |
| screensaver = conn(xcffib.screensaver.key) | |
| # Get the root window | |
| setup = conn.get_setup() | |
| screen = setup.roots[0] | |
| root = screen.root | |
| # Query screensaver version | |
| version_reply = screensaver.QueryVersion( | |
| xcffib.screensaver.MAJOR_VERSION, | |
| xcffib.screensaver.MINOR_VERSION | |
| ).reply() | |
| print(f"MIT-SCREEN-SAVER extension version: {version_reply.server_major_version}.{version_reply.server_minor_version}") | |
| print("Registered for screensaver events. Waiting for idle/active state changes...\n") | |
| # Register for screensaver events using SelectInput | |
| # NotifyMask will send us events when the screensaver state changes | |
| screensaver.SelectInput( | |
| root, | |
| xcffib.screensaver.Event.NotifyMask | xcffib.screensaver.Event.CycleMask, | |
| ) | |
| conn.flush() | |
| try: | |
| # Event loop - wait for screensaver events | |
| while True: | |
| event = conn.wait_for_event() | |
| if event is None: | |
| print("Connection lost") | |
| break | |
| handle_screensaver_event(event) | |
| except KeyboardInterrupt: | |
| print("\n\nMonitoring stopped.") | |
| finally: | |
| conn.disconnect() | |
| def handle_screensaver_event(event): | |
| """ | |
| Handle a screensaver NotifyEvent. | |
| Args: | |
| event: xcffib.screensaver.NotifyEvent | |
| """ | |
| # State can be: Off (0), On (1), Cycle (2), Disabled (3) | |
| state_names = { | |
| xcffib.screensaver.State.Off: "OFF", | |
| xcffib.screensaver.State.On: "ON", | |
| xcffib.screensaver.State.Cycle: "CYCLE", | |
| xcffib.screensaver.State.Disabled: "DISABLED" | |
| } | |
| # Kind can be: Blanked (0), Internal (1), External (2) | |
| kind_names = { | |
| xcffib.screensaver.Kind.Blanked: "Blanked", | |
| xcffib.screensaver.Kind.Internal: "Internal", | |
| xcffib.screensaver.Kind.External: "External" | |
| } | |
| state = state_names.get(event.state, f"Unknown({event.state})") | |
| kind = kind_names.get(event.kind, f"Unknown({event.kind})") | |
| forced = "forced" if event.forced else "not forced" | |
| print(f"Screensaver event: state={state}, kind={kind}, {forced}, time={event.time}") | |
| if event.state == xcffib.screensaver.State.On: | |
| print(" → User is now IDLE (screensaver activated)") | |
| elif event.state == xcffib.screensaver.State.Off: | |
| print(" → User is now ACTIVE (screensaver deactivated)") | |
| elif event.state == xcffib.screensaver.State.Cycle: | |
| print(" → Screensaver cycle event") | |
| else: | |
| print(f" → Screensaver {event} event") | |
| if __name__ == "__main__": | |
| monitor_screensaver_events() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment