AtlatestRepositorysigil-wm
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>10
static 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;17
}19
int 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;118
}