AtlatestRepositorysigil-wm

sigil-wm / tree / testx11-client.c

1/* SPDX-License-Identifier: BSD-3-Clause */
2#include <stdbool.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8#include <xcb/xcb.h>
9
10static xcb_atom_t atom(xcb_connection_t *connection, const char *name) {
11 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection,
12 xcb_intern_atom(connection, false, strlen(name), name), NULL);
13 if (!reply) exit(2);
14 xcb_atom_t result = reply->atom;
15 free(reply);
16 return result;
19int main(int argc, char **argv) {
20 bool override = argc > 1 && !strcmp(argv[1], "override");
21 int screen_index;
22 xcb_connection_t *connection = xcb_connect(NULL, &screen_index);
23 if (xcb_connection_has_error(connection)) return 2;
24 xcb_screen_iterator_t screens = xcb_setup_roots_iterator(xcb_get_setup(connection));
25 while (screen_index-- > 0) xcb_screen_next(&screens);
26 xcb_screen_t *screen = screens.data;
27 xcb_window_t window = xcb_generate_id(connection);
28 uint32_t values[] = {override ? 0x00cc44 : 0xcc2244,
29 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
30 XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE};
31 xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root,
32 10, 20, 320, 240, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual,
33 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values);
34 if (override) {
35 uint32_t enabled = 1;
36 xcb_change_window_attributes(connection, window, XCB_CW_OVERRIDE_REDIRECT, &enabled);
37 }
38 const char class[] = "sigil-wm-test\0SigilWmTest\0";
39 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_CLASS,
40 XCB_ATOM_STRING, 8, sizeof(class) - 1, class);
41 const char *title = override ? "Override client" : "Managed client";
42 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME,
43 XCB_ATOM_STRING, 8, strlen(title), title);
44 uint32_t pid = getpid();
45 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, atom(connection, "_NET_WM_PID"),
46 XCB_ATOM_CARDINAL, 32, 1, &pid);
47 xcb_atom_t delete_window = atom(connection, "WM_DELETE_WINDOW");
48 xcb_atom_t protocols = atom(connection, "WM_PROTOCOLS");
49 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, protocols, XCB_ATOM_ATOM,
50 32, 1, &delete_window);
51 xcb_gcontext_t gc = xcb_generate_id(connection);
52 uint32_t foreground = override ? 0x00cc44 : 0xcc2244;
53 xcb_create_gc(connection, gc, window, XCB_GC_FOREGROUND, &foreground);
54 xcb_map_window(connection, window);
55 xcb_rectangle_t initial_area = {0, 0, 320, 240};
56 xcb_poly_fill_rectangle(connection, window, gc, 1, &initial_area);
57 xcb_flush(connection);
58 printf("X11_WINDOW=%u\n", window);
59 fflush(stdout);
60 bool running = true;
61 bool requested = false;
62 while (running) {
63 xcb_generic_event_t *event = xcb_wait_for_event(connection);
64 if (!event) break;
65 switch (event->response_type & 0x7f) {
66 case XCB_EXPOSE:
67 {
68 xcb_expose_event_t *expose = (void *)event;
69 xcb_rectangle_t area = {expose->x, expose->y, expose->width, expose->height};
70 xcb_poly_fill_rectangle(connection, window, gc, 1, &area);
71 }
72 xcb_flush(connection);
73 break;
74 case XCB_CONFIGURE_NOTIFY: {
75 xcb_configure_notify_event_t *configure = (void *)event;
76 printf("X11_GEOMETRY=%d,%d,%u,%u\n", configure->x, configure->y,
77 configure->width, configure->height);
78 break;
79 }
80 case XCB_FOCUS_IN:
81 puts("X11_FOCUS=1");
82 if(!override && !requested) {
83 requested=true;
84 for(unsigned direction=0;direction<=8;direction+=8) {
85 xcb_client_message_event_t request={.response_type=XCB_CLIENT_MESSAGE,
86 .format=32,.window=window,.type=atom(connection,"_NET_WM_MOVERESIZE")};
87 request.data.data32[0]=48;
88 request.data.data32[1]=64;
89 request.data.data32[2]=direction;
90 request.data.data32[3]=1;
91 request.data.data32[4]=1;
92 xcb_send_event(connection,false,screen->root,
93 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT|XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
94 (const char *)&request);
95 }
96 xcb_flush(connection);
97 }
98 break;
99 case XCB_KEY_PRESS:
100 case XCB_KEY_RELEASE: {
101 xcb_key_press_event_t *key = (void *)event;
102 printf("X11_KEY=%u,%u\n", key->detail, (event->response_type & 0x7f) == XCB_KEY_PRESS);
103 break;
104 }
105 case XCB_CLIENT_MESSAGE: {
106 xcb_client_message_event_t *message = (void *)event;
107 if (message->type == protocols && message->data.data32[0] == delete_window) running = false;
108 break;
109 }
110 }
111 fflush(stdout);
112 free(event);
113 }
114 xcb_destroy_window(connection, window);
115 xcb_flush(connection);
116 xcb_disconnect(connection);
117 return 0;