##// END OF EJS Templates
enable xwl
Tsuki -
r5:996174ee93eb default
parent child Browse files
Show More
@@ -1,6 +1,6
1 1 option(
2 2 'xwayland',
3 3 type: 'boolean',
4 value: false,
4 value: true,
5 5 description: 'Enable XWayland support',
6 6 )
@@ -1,516 +1,516
1 1 #define _GNU_SOURCE
2 2 #include "arg.h"
3 3 #include <poll.h>
4 4 #include <stdio.h>
5 5 #include <stdlib.h>
6 6 #include <string.h>
7 7 #include <sys/socket.h>
8 8 #include <wayland-client.h>
9 9 #include <wayland-util.h>
10 10 #include "dwl-ipc-unstable-v2-protocol.h"
11 11
12 12 #define die(fmt, ...) do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } while (0)
13 13
14 14 char *argv0;
15 15
16 16 static enum {
17 17 NONE = 0,
18 18 SET = 1<<0,
19 19 GET = 1<<1,
20 20 WATCH = 1<<2 | GET,
21 21 } mode = NONE;
22 22
23 23 static int Oflag;
24 24 static int Tflag;
25 25 static int Lflag;
26 26 static int Pflag;
27 27 static int Fflag;
28 28 static int oflag;
29 29 static int tflag;
30 30 static int lflag;
31 31 static int cflag;
32 32 static int vflag;
33 33 static int mflag;
34 34 static int fflag;
35 35
36 36 static uint32_t occ, seltags, sel, urg;
37 37
38 38 static char *output_name;
39 39 static char *focused_output;
40 40 static uint32_t tagcount;
41 41 static char *tagset;
42 42 static char *layout_name;
43 43 static size_t layoutcount, layout_idx;
44 44 static char *client_tags;
45 45
46 46 struct output {
47 47 char *output_name;
48 48 uint32_t name;
49 49 };
50 50 static size_t outputs_buflen = 4;
51 51 static struct output *outputs;
52 52 static size_t outputcount;
53 53
54 54 static struct wl_display *display;
55 55 static struct wl_registry *registry;
56 56 static struct zdwl_ipc_manager_v2 *dwl_ipc_manager;
57 57
58 58 static void
59 59 dwl_ipc_tags(void *data, struct zdwl_ipc_manager_v2 *dwl_ipc_manager, uint32_t count)
60 60 {
61 61 tagcount = count;
62 62 if (Tflag && mode & GET) printf("%d\n", tagcount);
63 63 }
64 64
65 65 static void
66 66 dwl_ipc_layout(void *data, struct zdwl_ipc_manager_v2 *dwl_ipc_manager, const char *name)
67 67 {
68 68 if (lflag && mode & SET && strcmp(layout_name, name) == 0)
69 69 layout_idx = layoutcount;
70 70 if (Lflag && mode & GET) printf("%s\n", name);
71 71 layoutcount++;
72 72 }
73 73
74 74 static const struct zdwl_ipc_manager_v2_listener dwl_ipc_listener = {
75 75 .tags = dwl_ipc_tags,
76 76 .layout = dwl_ipc_layout
77 77 };
78 78
79 79 static void
80 80 dwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output)
81 81 {
82 82 if (!vflag) return;
83 83 char *oname = data;
84 84 if (oname) printf("%s ", oname);
85 85 printf("toggle\n");
86 86 }
87 87
88 88 static void
89 89 dwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
90 90 uint32_t active)
91 91 {
92 92 if (active && (!output_name || !*output_name))
93 93 output_name = strdup(data);
94 94 if (active) {
95 95 free(focused_output);
96 96 focused_output = data ? strdup(data) : NULL;
97 97 }
98 98 if (!oflag) return;
99 99 char *oname = data;
100 100 if (oname) printf("%s ", oname);
101 101 printf("selmon %u\n", !!active);
102 102 }
103 103
104 104 static void
105 105 dwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
106 106 uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused)
107 107 {
108 108 if (!tflag) return;
109 109 if (state != ZDWL_IPC_OUTPUT_V2_TAG_STATE_NONE) seltags |= 1<<tag;
110 110 if (state == ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) urg |= 1<<tag;
111 111 if (clients > 0) occ |= 1<<tag;
112 112 if (!(mode & GET)) return;
113 113 if (data) printf("%s ", (char *)data);
114 114 printf("tag %u %u %u %u\n", tag, state, clients, focused);
115 115 }
116 116
117 117 static void
118 118 dwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
119 119 uint32_t layout)
120 120 {
121 121 }
122 122
123 123 static void
124 124 dwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
125 125 const char *layout)
126 126 {
127 127 if (!(lflag && mode & GET)) return;
128 128 if (data) printf("%s ", (char *)data);
129 129 printf("layout %s\n", layout);
130 130 }
131 131
132 132 static void
133 133 dwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
134 134 const char *title)
135 135 {
136 136 if (!(cflag && mode & GET)) return;
137 137 if (data) printf("%s ", (char *)data);
138 138 printf("title %s\n", title);
139 139 }
140 140
141 141 static void
142 142 dwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
143 143 const char *appid)
144 144 {
145 145 if (!(cflag && mode & GET)) return;
146 146 if (data) printf("%s ", (char *)data);
147 147 printf("appid %s\n", appid);
148 148 }
149 149
150 150 static void
151 151 dwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
152 152 uint32_t is_fullscreen)
153 153 {
154 154 if (!mflag) return;
155 155 if (data) printf("%s ", (char *)data);
156 156 printf("fullscreen %u\n", is_fullscreen);
157 157 }
158 158
159 159 static void
160 160 dwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output,
161 161 uint32_t is_floating)
162 162 {
163 163 if (!fflag) return;
164 164 if (data) printf("%s ", (char *)data);
165 165 printf("floating %u\n", is_floating);
166 166 }
167 167
168 168 static void
169 169 dwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output)
170 170 {
171 171 if (mode & SET) {
172 172 if (data && !(output_name && strcmp(output_name, (char *)data) == 0)) return;
173 173 if (lflag) {
174 174 if (layout_idx == 0) {
175 175 for (char *c = layout_name; *c; c++) {
176 176 if (*c < '0' || *c > '9')
177 177 die("bad layout %s", layout_name);
178 178 layout_idx = *c-'0' + layout_idx*10;
179 179 }
180 180 }
181 181 if (layout_idx >= layoutcount)
182 182 die("bad layout %s", layout_name);
183 183 zdwl_ipc_output_v2_set_layout(dwl_ipc_output, layout_idx);
184 184 }
185 185 if (tflag) {
186 186 uint32_t mask = seltags;
187 187 char *t = tagset;
188 188 uint32_t i = 0;
189 189 int toggle = 1;
190 190
191 191 if (*t == '!') {
192 192 toggle = 0;
193 193 t++;
194 194 }
195 195
196 196 for (; *t && *t >= '0' && *t <= '9'; t++)
197 197 i = *t-'0' + i*10;
198 198
199 199 if (toggle && !*t) mask = 1<<i;
200 200
201 201 for (; *t; t++, i++) {
202 202 switch (*t) {
203 203 case '-':
204 204 mask &= ~(1<<i);
205 205 break;
206 206 case '+':
207 207 mask |= 1<<i;
208 208 break;
209 209 case '^':
210 210 mask ^= 1<<i;
211 211 break;
212 212 }
213 213 }
214 214
215 215 if (i > tagcount) die("bad tagset %s", tagset);
216 216
217 217 zdwl_ipc_output_v2_set_tags(dwl_ipc_output, mask, toggle);
218 218 }
219 219 if (cflag) {
220 220 uint32_t and = ~0, xor = 0;
221 221 char *t = client_tags;
222 222 uint32_t i = 0;
223 223
224 224 for (; *t && *t >= '0' && *t <= '9'; t++)
225 225 i = *t-'0' + i*10;
226 226
227 227 if (!*t) {
228 228 and = 0;
229 229 xor = 1<<i;
230 230 }
231 231
232 232 for (; *t; t++, i++) {
233 233 switch (*t) {
234 234 case '-':
235 235 and &= ~(1<<i);
236 236 break;
237 237 case '+':
238 238 and &= ~(1<<i);
239 239 xor |= 1<<i;
240 240 break;
241 241 case '^':
242 242 xor |= 1<<i;
243 243 break;
244 244 }
245 245 }
246 246 if (i > tagcount) die("bad client tagset %s", client_tags);
247 247
248 248 zdwl_ipc_output_v2_set_client_tags(dwl_ipc_output, and, xor);
249 249 }
250 250 wl_display_flush(display);
251 251 exit(0);
252 252 } else {
253 253 if (Fflag && mode == WATCH && focused_output)
254 254 printf("focusmon %s\n", focused_output);
255 255 if (tflag) {
256 256 if (data) printf("%s ", (char *)data);
257 257 printf("tags %u %u %u %u\n", occ, seltags, sel, urg);
258 258 occ = seltags = sel = urg = 0;
259 259 }
260 260 }
261 261 fflush(stdout);
262 262 }
263 263
264 264 static const struct zdwl_ipc_output_v2_listener dwl_ipc_output_listener = {
265 265 .toggle_visibility = dwl_ipc_output_toggle_visibility,
266 266 .active = dwl_ipc_output_active,
267 267 .tag = dwl_ipc_output_tag,
268 268 .layout = dwl_ipc_output_layout,
269 269 .title = dwl_ipc_output_title,
270 270 .appid = dwl_ipc_output_appid,
271 271 .layout_symbol = dwl_ipc_output_layout_symbol,
272 272 .fullscreen = dwl_ipc_output_fullscreen,
273 273 .floating = dwl_ipc_output_floating,
274 274 .frame = dwl_ipc_output_frame,
275 275 };
276 276
277 277 static void
278 278 wl_output_name(void *data, struct wl_output *output, const char *name)
279 279 {
280 280 if (outputs) {
281 281 struct output *o = (struct output *)data;
282 282 o->output_name = strdup(name);
283 283 printf("+ ");
284 284 }
285 285 if (Oflag) printf("%s\n", name);
286 286 if (output_name && *output_name && strcmp(output_name, name) != 0) {
287 287 wl_output_release(output);
288 288 return;
289 289 }
290 290 if (dwl_ipc_manager) {
291 291 struct zdwl_ipc_output_v2 *dwl_ipc_output =
292 292 zdwl_ipc_manager_v2_get_output(dwl_ipc_manager, output);
293 293 zdwl_ipc_output_v2_add_listener(dwl_ipc_output, &dwl_ipc_output_listener,
294 294 output_name && *output_name ? NULL : strdup(name));
295 295 }
296 296 }
297 297
298 298 static void
299 299 wl_output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t w, int32_t h, int32_t subpixel, const char *make, const char *model, int32_t transform) {
300 300 }
301 301
302 302 static void
303 303 wl_output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
304 304 {
305 305 }
306 306
307 307 static void
308 308 wl_output_done(void *data, struct wl_output *wl_output)
309 309 {
310 310 }
311 311
312 312 static void
313 313 wl_output_scale(void *data, struct wl_output *wl_output, int32_t factor)
314 314 {
315 315 }
316 316
317 317 static void
318 318 wl_output_description(void *data, struct wl_output *output, const char *description)
319 319 {
320 320 }
321 321
322 322 static const struct wl_output_listener output_listener = {
323 323 .geometry = wl_output_geometry,
324 324 .mode = wl_output_mode,
325 325 .done = wl_output_done,
326 326 .scale = wl_output_scale,
327 327 .name = wl_output_name,
328 328 .description = wl_output_description,
329 329 };
330 330
331 331 static void
332 332 global_add(void *data, struct wl_registry *wl_registry,
333 333 uint32_t name, const char *interface, uint32_t version)
334 334 {
335 335 if (strcmp(interface, wl_output_interface.name) == 0) {
336 336 struct wl_output *o = wl_registry_bind(
337 337 wl_registry, name, &wl_output_interface,
338 338 WL_OUTPUT_NAME_SINCE_VERSION);
339 339 wl_output_add_listener(o, &output_listener, outputs ? &outputs[outputcount] : NULL);
340 340 if (!outputs) return;
341 341 if (outputcount >= outputs_buflen) {
342 342 outputs_buflen *= 2;
343 343 outputs = reallocarray(outputs, outputs_buflen, sizeof(struct output));
344 344 }
345 345 outputs[outputcount].name = name;
346 346 outputcount++;
347 347 } else if (strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
348 348 dwl_ipc_manager = wl_registry_bind(wl_registry, name,
349 349 &zdwl_ipc_manager_v2_interface, version < 2 ? version : 2);
350 350 zdwl_ipc_manager_v2_add_listener(dwl_ipc_manager, &dwl_ipc_listener, NULL);
351 351 }
352 352 }
353 353
354 354 static void
355 355 global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)
356 356 {
357 357 if (!outputs) return;
358 358 for (size_t i = 0; i < outputcount; i++) {
359 359 if (outputs[i].name == name) {
360 360 printf("- %s\n", outputs[i].output_name);
361 361 free(outputs[i].output_name);
362 362 outputs[i] = outputs[--outputcount];
363 363 }
364 364 }
365 365 }
366 366
367 367 static const struct wl_registry_listener registry_listener = {
368 368 .global = global_add,
369 369 .global_remove = global_remove,
370 370 };
371 371
372 372 static void
373 373 usage(int code)
374 374 {
375 375 fprintf(code ? stderr : stdout,
376 376 "usage:"
377 377 "\t%1$s [-OTLPF]\n"
378 378 "\t%1$s [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>]\n"
379 379 "\t%1$s [-o <output>] (-g | -w) [-FOotlcvmf]\n",
380 380 argv0);
381 381 exit(code);
382 382 }
383 383
384 384 int
385 385 main(int argc, char *argv[])
386 386 {
387 387 ARGBEGIN {
388 388 case '?': case 'h':
389 389 usage(0); break;
390 390 case 's':
391 391 if (mode != NONE) usage(1);
392 392 mode = SET;
393 393 break;
394 394 case 'g':
395 395 if (mode != NONE) usage(1);
396 396 mode = GET;
397 397 break;
398 398 case 'w':
399 399 if (mode != NONE) usage(1);
400 400 mode = WATCH;
401 401 break;
402 402 case 'o':
403 403 if (mode & SET)
404 404 output_name = EARGF(usage(1));
405 405 else if (mode & GET || !(output_name = ARGF()))
406 406 oflag = 1;
407 407 break;
408 408 case 't':
409 409 tflag = 1;
410 410 if (mode & GET) break;
411 411 mode = SET;
412 412 tagset = EARGF(usage(1));
413 413 break;
414 414 case 'l':
415 415 lflag = 1;
416 416 if (mode & GET) break;
417 417 mode = SET;
418 418 layout_name = EARGF(usage(1));
419 419 break;
420 420 case 'c':
421 421 cflag = 1;
422 422 if (mode & GET) break;
423 423 mode = SET;
424 424 client_tags = EARGF(usage(1));
425 425 break;
426 426 case 'O':
427 427 Oflag = 1;
428 428 if (mode & SET) usage(1);
429 429 if (mode & WATCH)
430 430 outputs = malloc(outputs_buflen * sizeof(struct output));
431 431 else
432 432 mode = GET;
433 433 break;
434 434 case 'T':
435 435 Tflag = 1;
436 436 if (mode && mode != GET) usage(1);
437 437 mode = GET;
438 438 break;
439 439 case 'L':
440 440 Lflag = 1;
441 441 if (mode && mode != GET) usage(1);
442 442 mode = GET;
443 443 break;
444 444 case 'P':
445 445 Pflag = 1;
446 446 if (mode && mode != GET) usage(1);
447 447 mode = GET;
448 448 break;
449 449 case 'F':
450 450 Fflag = 1;
451 451 if (mode && mode != GET) usage(1);
452 452 mode = GET;
453 453 break;
454 454 case 'v':
455 455 vflag = 1;
456 456 if (mode & SET) usage(1);
457 457 mode |= GET;
458 458 break;
459 459 case 'm':
460 460 mflag = 1;
461 461 if (mode & SET) usage(1);
462 462 mode |= GET;
463 463 break;
464 464 case 'f':
465 465 fflag = 1;
466 466 if (mode & SET) usage(1);
467 467 mode |= GET;
468 468 break;
469 469 default:
470 470 fprintf(stderr, "%s: bad option: -%c\n", argv0, ARGC());
471 471 usage(1);
472 472 } ARGEND
473 473 if (argc > 0) {
474 474 fprintf(stderr, "%s: bad args:", argv0);
475 475 for (; *argv; argv++)
476 476 fprintf(stderr, " %s", argv[0]);
477 477 fprintf(stderr, "\n");
478 478 usage(1);
479 479 }
480 480 if (mode == NONE) usage(1);
481 481 if (mode & GET && !(oflag || tflag || lflag || Oflag || Tflag || Lflag || Pflag || Fflag || cflag || vflag || mflag || fflag))
482 482 oflag = tflag = lflag = cflag = vflag = mflag = fflag = Fflag = 1;
483 483
484 484 display = wl_display_connect(NULL);
485 485 if (!display) die("bad display");
486 486
487 487 if (Pflag) {
488 488 int fd = wl_display_get_fd(display);
489 489 struct ucred ucred;
490 490 socklen_t len = sizeof(struct ucred);
491 491 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
492 492 die("bad getsockopt");
493 493 printf("%d\n", ucred.pid);
494 494 }
495 495
496 496 registry = wl_display_get_registry(display);
497 497 if (!registry) die("bad registry");
498 498
499 499 wl_registry_add_listener(registry, &registry_listener, NULL);
500 500
501 501 wl_display_dispatch(display);
502 wl_display_roundtrip(display);
502 wl_display_roundtrip(display);
503 503
504 504 if (!dwl_ipc_manager && (mode & SET || tflag || lflag || Tflag || Lflag || cflag || vflag || mflag || fflag))
505 505 die("bad dwl-ipc protocol");
506 506
507 507 wl_display_roundtrip(display);
508 508
509 509 if (Fflag && !(mode == WATCH) && focused_output)
510 510 printf("focusmon %s\n", focused_output);
511 511
512 512 if (mode == WATCH)
513 513 while (wl_display_dispatch(display) != -1);
514 514
515 515 return 0;
516 516 }
General Comments 0
You need to be logged in to leave comments. Login now