A => .editorconfig +9 -0
@@ 1,9 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+trim_trailing_whitespace = true
+indent_style = tab
+indent_size = 4
A => .gitignore +1 -0
A => LICENSE +21 -0
@@ 1,21 @@
+MIT License
+
+Copyright (c) 2023 Simon Ser
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
A => README.md +7 -0
@@ 1,7 @@
+# sesame
+
+Unconditonally unlock the session. Useful when the screen locker has crashed.
+
+## License
+
+MIT
A => main.c +85 -0
@@ 1,85 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wayland-client.h>
+
+#include "ext-session-lock-v1-protocol.h"
+
+static struct ext_session_lock_manager_v1 *session_lock_manager = NULL;
+static bool locked = false;
+
+static void lock_handle_locked(void *data, struct ext_session_lock_v1 *lock) {
+ locked = true;
+}
+
+static void lock_handle_finished(void *data, struct ext_session_lock_v1 *lock) {
+ fprintf(stderr, "compositor refused to lock the session\n");
+ exit(1);
+}
+
+static const struct ext_session_lock_v1_listener lock_listener = {
+ .locked = lock_handle_locked,
+ .finished = lock_handle_finished,
+};
+
+static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) {
+ if (strcmp(interface, ext_session_lock_manager_v1_interface.name) == 0) {
+ session_lock_manager = wl_registry_bind(registry, name, &ext_session_lock_manager_v1_interface, 1);
+ }
+}
+
+static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
+ // no-op
+}
+
+static const struct wl_registry_listener registry_listener = {
+ .global = registry_handle_global,
+ .global_remove = registry_handle_global_remove,
+};
+
+int main(int argc, char *argv[]) {
+ struct wl_display *display = wl_display_connect(NULL);
+ if (display == NULL) {
+ fprintf(stderr, "failed to connect to display\n");
+ return 1;
+ }
+
+ struct wl_registry *registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, ®istry_listener, NULL);
+
+ if (wl_display_roundtrip(display) < 0) {
+ fprintf(stderr, "wl_display_roundtrip() failed\n");
+ return 1;
+ }
+
+ wl_registry_destroy(registry);
+
+ if (session_lock_manager == NULL) {
+ fprintf(stderr, "compositor doesn't support ext-session-lock-v1\n");
+ return 1;
+ }
+
+ struct ext_session_lock_v1 *lock = ext_session_lock_manager_v1_lock(session_lock_manager);
+ ext_session_lock_v1_add_listener(lock, &lock_listener, NULL);
+
+ while (!locked) {
+ if (wl_display_dispatch(display) < 0) {
+ fprintf(stderr, "wl_display_dispatch() failed\n");
+ return 1;
+ }
+ }
+
+ ext_session_lock_v1_unlock_and_destroy(lock);
+
+ if (wl_display_roundtrip(display) < 0) {
+ fprintf(stderr, "wl_display_roundtrip() failed\n");
+ return 1;
+ }
+
+ ext_session_lock_manager_v1_destroy(session_lock_manager);
+ wl_display_disconnect(display);
+
+ return 0;
+}
A => meson.build +26 -0
@@ 1,26 @@
+project(
+ 'sesame',
+ 'c',
+ default_options: ['c_std=c11', 'warning_level=2', 'werror=true'],
+)
+
+add_project_arguments(
+ '-D_POSIX_C_SOURCE=200809L',
+ '-Wno-unused-parameter',
+ language: 'c',
+)
+
+subdir('protocol')
+
+cc = meson.get_compiler('c')
+
+wayland_client = dependency('wayland-client')
+
+executable(
+ 'sesame',
+ ['main.c'] + protos_src,
+ dependencies: [
+ wayland_client,
+ ],
+ install: true,
+)
A => protocol/meson.build +27 -0
@@ 1,27 @@
+wayland_scanner = dependency('wayland-scanner', native: true, version: '>=1.14.91')
+wayland_scanner = find_program(wayland_scanner.get_variable('wayland_scanner'), native: true)
+
+wayland_protocols = dependency('wayland-protocols', version: '>=1.14')
+wp_dir = wayland_protocols.get_variable('pkgdatadir')
+
+wayland_scanner_code = generator(
+ wayland_scanner,
+ output: '@BASENAME@-protocol.c',
+ arguments: ['private-code', '@INPUT@', '@OUTPUT@'],
+)
+
+wayland_scanner_client = generator(
+ wayland_scanner,
+ output: '@BASENAME@-protocol.h',
+ arguments: ['client-header', '@INPUT@', '@OUTPUT@'],
+)
+
+client_protocols = [
+ wp_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
+]
+
+protos_src = []
+foreach xml : client_protocols
+ protos_src += wayland_scanner_code.process(xml)
+ protos_src += wayland_scanner_client.process(xml)
+endforeach