The open source OpenXR runtime
1// Copyright 2020-2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Small cli application to demonstrate use of libmonado.
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 * @author Pete Black <pblack@collabora.com>
8 */
9
10#include "monado.h"
11
12#include <ctype.h>
13#include <limits.h>
14#include <stddef.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <getopt.h>
18#include <stdbool.h>
19
20
21#define P(...) fprintf(stdout, __VA_ARGS__)
22#define PE(...) fprintf(stderr, __VA_ARGS__)
23#define CHECK_ID_EXIT(ID) \
24 do { \
25 if (ID < 0 || ID > INT_MAX) { \
26 PE("Invalid client index %i.\n", s_val); \
27 exit(1); \
28 } \
29 } while (false)
30
31typedef enum op_mode
32{
33 MODE_GET,
34 MODE_SET_PRIMARY,
35 MODE_SET_FOCUSED,
36 MODE_TOGGLE_IO,
37} op_mode_t;
38
39int
40get_mode(mnd_root_t *root)
41{
42 mnd_result_t mret = mnd_root_update_client_list(root);
43 if (mret != MND_SUCCESS) {
44 PE("Failed to get client list.\n");
45 exit(1);
46 }
47
48 uint32_t num_clients = 0;
49 mret = mnd_root_get_number_clients(root, &num_clients);
50 if (mret != MND_SUCCESS) {
51 PE("Failed to get client count.\n");
52 exit(1);
53 }
54
55 P("Clients: (%d)\n", num_clients);
56 for (uint32_t i = 0; i < num_clients; i++) {
57 uint32_t client_id = 0;
58 uint32_t flags = 0;
59 const char *name = NULL;
60
61 mret = mnd_root_get_client_id_at_index(root, i, &client_id);
62 if (mret != MND_SUCCESS) {
63 PE("Failed to get client id for index %u", i);
64 continue;
65 }
66
67 mret = mnd_root_get_client_state(root, client_id, &flags);
68 if (mret != MND_SUCCESS) {
69 PE("Failed to get client state for client id: %u (index: %u)", client_id, i);
70 continue;
71 }
72
73 mret = mnd_root_get_client_name(root, client_id, &name);
74 if (mret != MND_SUCCESS) {
75 PE("Failed to get client name for client id: %u (index: %u)", client_id, i);
76 continue;
77 }
78
79 P("\tid: % 8d"
80 "\tact: %d"
81 "\tdisp: %d"
82 "\tfoc: %d"
83 "\tio: %d"
84 "\tovly: %d"
85 "\t%s\n",
86 client_id, //
87 (flags & MND_CLIENT_SESSION_ACTIVE) != 0 ? 1 : 0, //
88 (flags & MND_CLIENT_SESSION_VISIBLE) != 0 ? 1 : 0, //
89 (flags & MND_CLIENT_SESSION_FOCUSED) != 0 ? 1 : 0, //
90 (flags & MND_CLIENT_IO_ACTIVE) != 0 ? 1 : 0, //
91 (flags & MND_CLIENT_SESSION_OVERLAY) != 0 ? 1 : 0, //
92 name);
93 }
94
95 return 0;
96}
97
98int
99set_primary(mnd_root_t *root, int client_index)
100{
101 mnd_result_t mret = mnd_root_set_client_primary(root, client_index);
102 if (mret != MND_SUCCESS) {
103 PE("Failed to set active client to index %d.\n", client_index);
104 return 1;
105 }
106
107 return 0;
108}
109
110int
111set_focused(mnd_root_t *root, int client_index)
112{
113 mnd_result_t mret = mnd_root_set_client_focused(root, client_index);
114 if (mret != MND_SUCCESS) {
115 PE("Failed to set focused client to index %d.\n", client_index);
116 return 1;
117 }
118
119 return 0;
120}
121
122int
123toggle_io(mnd_root_t *root, int client_index)
124{
125 mnd_result_t mret = mnd_root_toggle_client_io_active(root, client_index);
126 if (mret != MND_SUCCESS) {
127 PE("Failed to toggle io for client index %d.\n", client_index);
128 return 1;
129 }
130 return 0;
131}
132
133int
134main(int argc, char *argv[])
135{
136 op_mode_t op_mode = MODE_GET;
137
138 // parse arguments
139 int c;
140 int s_val = 0;
141
142 opterr = 0;
143 while ((c = getopt(argc, argv, "p:f:i:")) != -1) {
144 switch (c) {
145 case 'p':
146 s_val = atoi(optarg);
147 CHECK_ID_EXIT(s_val);
148 op_mode = MODE_SET_PRIMARY;
149 break;
150 case 'f':
151 s_val = atoi(optarg);
152 CHECK_ID_EXIT(s_val);
153 op_mode = MODE_SET_FOCUSED;
154 break;
155 case 'i':
156 s_val = atoi(optarg);
157 CHECK_ID_EXIT(s_val);
158 op_mode = MODE_TOGGLE_IO;
159 break;
160 case '?':
161 if (optopt == 's') {
162 PE("Option -s requires a client index to set.\n");
163 } else if (isprint(optopt)) {
164 PE("Option `-%c' unknown. Usage:\n", optopt);
165 PE(" -f <index>: Set focused client\n");
166 PE(" -p <index>: Set primary client\n");
167 PE(" -i <index>: Toggle whether client receives input\n");
168 } else {
169 PE("Option `\\x%x' unknown.\n", optopt);
170 }
171 exit(1);
172 default: exit(0);
173 }
174 }
175
176 mnd_root_t *root = NULL;
177 mnd_result_t mret;
178
179 mret = mnd_root_create(&root);
180 if (mret != MND_SUCCESS) {
181 PE("Failed to connect.");
182 return 1;
183 }
184
185 mret = mnd_root_update_client_list(root);
186 if (mret != MND_SUCCESS) {
187 PE("Failed to update client list.");
188 return 1;
189 }
190
191 switch (op_mode) {
192 case MODE_GET: exit(get_mode(root)); break;
193 case MODE_SET_PRIMARY: exit(set_primary(root, s_val)); break;
194 case MODE_SET_FOCUSED: exit(set_focused(root, s_val)); break;
195 case MODE_TOGGLE_IO: exit(toggle_io(root, s_val)); break;
196 default: P("Unrecognised operation mode.\n"); exit(1);
197 }
198
199 return 0;
200}