AtlatestRepositorysigil-wm

sigil-wm / tree / testpopup-constraints.c

1/* SPDX-License-Identifier: BSD-3-Clause */
2#include <errno.h>
3#include <poll.h>
4#include <signal.h>
5#include <stdbool.h>
6#include <stdint.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/wait.h>
11#include <time.h>
12#include <unistd.h>
13#include "api.h"
15static pid_t child;
16static void cleanup(void) {
17 if (child > 0) { kill(child, SIGKILL); waitpid(child, NULL, 0); }
19static void require(bool ok, const char *message) {
20 if (ok) return;
21 fprintf(stderr, "popup constraints: %s\n", message);
22 exit(2);
24static void send_words(int64_t *words, size_t count) {
25 struct wm_message command = {0};
26 require(count <= 16, "command size");
27 memcpy(command.word, words, count * sizeof(*words));
28 require(wm_send(&command) == 1, "command refused");
30#define SEND(...) send_words((int64_t[]){__VA_ARGS__}, sizeof((int64_t[]){__VA_ARGS__}) / sizeof(int64_t))
31static double seconds(void) {
32 struct timespec now;
33 clock_gettime(CLOCK_MONOTONIC, &now);
34 return now.tv_sec + now.tv_nsec / 1e9;
36int main(int argc, char **argv) {
37 require(argc == 3, "usage: popup-constraints toplevel|layer 0|1");
38 int selected = atoi(argv[2]);
39 require(selected == 0 || selected == 1, "output selection");
40 atexit(cleanup);
41 setvbuf(stdout, NULL, _IOLBF, 0);
42 require(wm_options(32, 2000) == 1 && wm_start() == 1, "start");
43 int outputs = 0, configured = 0, result = 2;
44 int64_t chosen = 0;
45 bool running = true, layer_configured = false;
46 int64_t admitted_popup = 0;
47 double deadline = seconds() + 20;
48 while (running && seconds() < deadline) {
49 struct pollfd fd = {.fd = wm_event_fd(), .events = POLLIN};
50 require(poll(&fd, 1, 50) >= 0 || errno == EINTR, "event poll");
51 struct wm_message event;
52 while (wm_next(&event)) {
53 int64_t *w = event.word;
54 switch (w[0]) {
55 case 2: {
56 if (outputs == selected) chosen = w[1];
57 int64_t output[] = {w[1], 1, 100 + outputs * 640, 60, 1000, 0, -1, 640, 480, 60000};
58 require(wm_submit(2, ++outputs, output, 10) == 1, "output configuration");
59 break;
60 }
61 case 24:
62 require(w[3] == 1, "output rejected");
63 if (++configured == 2) {
64 require(outputs == 2 && chosen, "two outputs");
65 SEND(25, chosen);
66 require(setenv("WAYLAND_DISPLAY", wm_socket(), 1) == 0, "socket name");
67 child = fork();
68 require(child >= 0, "fork");
69 if (!child) { execl("build/popup-client", "popup-client", argv[1], NULL); _exit(127); }
70 }
71 break;
72 case 14: SEND(2, w[1], 150, 150); break;
73 case 19:
74 if (w[14] && !layer_configured) {
75 layer_configured = true;
76 SEND(24, w[1], chosen, 150, 150);
77 }
78 break;
79 case 11: {
80 int64_t plan[] = {1, 1, w[1], 200, w[1], 580 + selected * 640, 350, 150, 150, 1, 1, 0, 0, 0};
81 require(wm_submit(1, 10, plan, 14) == 1, "parent placement");
82 break;
83 }
84 case 80:
85 if (admitted_popup != w[1]) {
86 admitted_popup = w[1];
87 SEND(20, w[1], w[3], w[4], w[5], w[6]);
88 }
89 break;
90 case 13: {
91 int status;
92 require(child > 0 && waitpid(child, &status, 0) == child, "client wait");
93 child = 0;
94 result = WIFEXITED(status) ? WEXITSTATUS(status) : 2;
95 SEND(1);
96 break;
97 }
98 case 7: require(w[2] == 0, "native failure"); running = false; break;
99 case 23: require(false, "plan rejected"); break;
100 case 98: require(false, "command rejected"); break;
101 }
102 }
103 }
104 require(!running, "timeout waiting for client");
105 require(wm_join() == 1, "join");
106 require(wm_stat(1) == 0 && wm_stat(2) == 0 && wm_stat(3) == 0 && wm_stat(7) == 0, "retained resources");
107 printf("POPUP_CONSTRAINTS=%s role=%s output=%d\n", result == 0 ? "PASS" : "FAIL", argv[1], selected);
108 return result;