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