Skip to content

Wayland support#4

Open
perk11 wants to merge 39 commits into
mainfrom
wayland-v2
Open

Wayland support#4
perk11 wants to merge 39 commits into
mainfrom
wayland-v2

Conversation

@perk11
Copy link
Copy Markdown
Owner

@perk11 perk11 commented Mar 15, 2026

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces initial Wayland support for runwhenidle by using the ext_idle_notification_v1 protocol, while keeping the existing X11/XScreenSaver polling as a fallback. It also adds helpers to infer missing graphical-session environment variables and a few small utility modules needed by the new backend.

Changes:

  • Add a Wayland idle backend (ext-idle-notify) with a poll-based event loop and PID-exit monitoring.
  • Add “best effort” inference for XDG_RUNTIME_DIR, WAYLAND_DISPLAY, and DISPLAY plus basic file/string utilities.
  • Update build/linking and README to reflect Wayland support and new sources.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
wayland.h Declares Wayland idle monitoring entry points.
wayland.c Implements Wayland connection/registry binding and idle notification object management.
environment_guessing.h Declares helpers to infer session env vars and open X11 display best-effort.
environment_guessing.c Implements env inference + Wayland/X11 socket discovery logic.
ext-idle-notify-v1-client-protocol.h Generated client header for ext-idle-notify-v1 protocol.
ext-idle-notify-v1-protocol.c Generated protocol interface definitions for linking against libwayland-client.
main.c Integrates Wayland event loop first, then falls back to X11 polling; adds SIGCHLD handling and timer/poll logic.
process_handling.h Exposes a helper to open a pidfd for process-exit monitoring.
process_handling.c Implements pidfd open via syscall() with ENOSYS fallback.
file_utils.h Declares filesystem helpers used by environment inference.
file_utils.c Implements socket/dir/file checks and home-dir lookup.
string_utils.h Declares is_string_null_or_empty.
string_utils.c Implements is_string_null_or_empty.
README.md Documents Wayland vs X11 behavior and updates known-issues note.
Makefile Links Wayland client library and builds the new sources.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread main.c Outdated
Comment thread main.c
Comment thread main.c
command_paused = 1;
}
}
}
Comment thread environment_guessing.h
Comment thread wayland.h
Comment thread main.c Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 10 comments.

Comments suppressed due to low confidence (1)

main.c:464

  • After introducing the resume_paused_command_on_user_idle() helper, the original inline logic (the if (!quiet) printf block, the call to resume_command_recursively(pid), and the command_paused = 0 assignment) was not removed. As a result, when the user becomes idle and the command is resumed, the "Lack of user activity detected." message is printed twice and resume_command_recursively(pid) is invoked twice. The duplicated block should be deleted.
            resume_paused_command_on_user_idle();
            if (!quiet) {
                printf("Lack of user activity detected. ");
                //intentionally no new line here, resume_command will print the rest of the message.
            }
            resume_command_recursively(pid);
            command_paused = 0;

Comment thread main.c Outdated
Comment thread descriptor_utils.c Outdated
Comment thread process_handling.c Outdated
Comment thread README.md Outdated
Comment thread main.c
Comment thread wayland.c Outdated
Comment thread environment_guessing.c
Comment thread environment_guessing.h
Comment thread file_utils.h
Comment thread environment_guessing.c
perk11 and others added 9 commits May 29, 2026 21:42
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
… suffixes starting with a digit (e.g., `wayland-1abc`) were incorrectly accepted and parsed as numeric.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

main.c:466

  • After extracting the resume helper, the original message-and-resume block was kept in place. The result is that when the user becomes idle on X11, resume_paused_command_on_user_idle() first prints "Lack of user activity detected." and calls resume_command_recursively(pid), and then lines 461–466 print the same message and call resume_command_recursively(pid) a second time. The command is resumed twice (sending SIGCONT to an already-running process is harmless but misleading) and the user-facing message is duplicated. The leftover if (!quiet) { printf(...); } + resume_command_recursively(pid); command_paused = 0; block should be removed since resume_paused_command_on_user_idle() already performs all of it.
            resume_paused_command_on_user_idle();
            if (!quiet) {
                printf("Lack of user activity detected. ");
                //intentionally no new line here, resume_command will print the rest of the message.
            }
            resume_command_recursively(pid);
            command_paused = 0;

Comment thread README.md Outdated
Comment thread environment_guessing.c Outdated
Comment thread wayland.c
Comment thread Makefile Outdated
Comment thread main.c
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

main.c:465

  • Duplicate resume on idle: resume_paused_command_on_user_idle() already prints "Lack of user activity detected. ", calls resume_command_recursively(pid), and sets command_paused = 0. The block below it (lines 460–465) repeats all three steps, so on every idle transition the command is resumed twice and the message is printed twice. Remove the duplicated block.
            resume_paused_command_on_user_idle();
            if (!quiet) {
                printf("Lack of user activity detected. ");
                //intentionally no new line here, resume_command will print the rest of the message.
            }
            resume_command_recursively(pid);
            command_paused = 0;

Comment thread main.c
Comment thread main.c
Comment thread environment_guessing.c Outdated
Comment thread environment_guessing.c
Comment thread README.md Outdated
Comment thread process_handling.c Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 10 comments.

Comment thread process_handling.c Outdated
Comment thread wayland.c
Comment on lines +85 to +94
if (wayland_seat == NULL || wayland_idle_notifier == NULL) {
wl_registry_destroy(wayland_registry);
wayland_registry = NULL;
wl_display_disconnect(wayland_display);
wayland_display = NULL;
wayland_seat = NULL;
wayland_idle_notifier = NULL;
wayland_idle_notify_available = 0;
return 0;
}
Comment thread main.c
Comment thread main.c
Comment thread main.c
Comment on lines +204 to +218
process_exit_wait_file_descriptor = open_pid_file_descriptor_for_process(pid);
if (process_exit_wait_file_descriptor == -1) {
const int saved_errno = errno;
fprintf_error("Failed to open file descriptor for pid %d: %s\n", pid, strerror(saved_errno));

if (external_pid != 0) {
external_pid_fallback_check_timer_file_descriptor = create_periodic_timer_file_descriptor_every_ms(1000);
if (external_pid_fallback_check_timer_file_descriptor == -1) {
const int timer_errno = errno;
fprintf_error("Failed to create periodic timer file descriptor for external pid fallback: %s\n",
strerror(timer_errno));
goto run_wayland_idle_event_loop_cleanup;
}
}
}
Comment thread main.c
Comment thread environment_guessing.c
Comment thread environment_guessing.c
Comment thread Makefile
Comment thread README.md
@perk11 perk11 changed the title WIP Wayland support Wayland support May 30, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.

Comment thread main.c
Comment on lines +429 to +437
}

close_file_descriptor_if_open(&start_monitor_timer_file_descriptor, "start-monitor timer");
close_file_descriptor_if_open(&process_exit_wait_file_descriptor, "process-exit");
close_file_descriptor_if_open(&external_pid_fallback_check_timer_file_descriptor, "external-pid fallback timer");
if (verbose) {
fprintf(stderr, "Wayland connection lost or loop finished.\n");
}
return wait_for_pid_to_exit_checking_for_signals();
Comment thread wayland.c
Comment on lines +85 to +94
if (wayland_seat == NULL || wayland_idle_notifier == NULL) {
wl_registry_destroy(wayland_registry);
wayland_registry = NULL;
wl_display_disconnect(wayland_display);
wayland_display = NULL;
wayland_seat = NULL;
wayland_idle_notifier = NULL;
wayland_idle_notify_available = 0;
return 0;
}
Comment thread wayland.c
Comment on lines +100 to +128
int start_wayland_idle_notification_object(
const struct ext_idle_notification_v1_listener *wayland_idle_notification_listener) {
if (wayland_idle_notification != NULL) {
return 0;
}
if (!wayland_idle_notify_available) {
return -1;
}

uint32_t timeout_ms_for_protocol = (user_idle_timeout_ms > UINT32_MAX)
? UINT32_MAX
: (uint32_t) user_idle_timeout_ms;

if (wayland_idle_notifier_version >= 2) {
wayland_idle_notification = ext_idle_notifier_v1_get_input_idle_notification(
wayland_idle_notifier, timeout_ms_for_protocol, wayland_seat);
} else {
wayland_idle_notification = ext_idle_notifier_v1_get_idle_notification(
wayland_idle_notifier, timeout_ms_for_protocol, wayland_seat);
}

if (!wayland_idle_notification) {
return -1;
}

ext_idle_notification_v1_add_listener(wayland_idle_notification, wayland_idle_notification_listener, NULL);
wl_display_flush(wayland_display);
return 1;
}
Comment thread environment_guessing.c
Comment on lines +51 to +67
if (!found) {
found = 1;
best_numeric_suffix = (numeric_suffix >= 0) ? numeric_suffix : INT_MAX;
snprintf(best_name, sizeof(best_name), "%s", entry->d_name);
continue;
}

if (numeric_suffix >= 0 && numeric_suffix < best_numeric_suffix) {
best_numeric_suffix = numeric_suffix;
snprintf(best_name, sizeof(best_name), "%s", entry->d_name);
continue;
}

if (best_numeric_suffix == INT_MAX && numeric_suffix == -1) {
snprintf(best_name, sizeof(best_name), "%s", entry->d_name);
}
}
Comment thread environment_guessing.c
Comment on lines +139 to +151
const char *digits = entry->d_name + 1;
if (*digits < '0' || *digits > '9') {
continue;
}

int display_number = (int)strtol(digits, NULL, 10);

char socket_path[PATH_MAX];
snprintf(socket_path, sizeof(socket_path), "%s/%s", x11_socket_dir, entry->d_name);

if (!file_is_socket(socket_path)) {
continue;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants