libdraw

Minimal window and drawing library
git clone http://git.omkov.net/libdraw
Log | Tree | Refs | Download

libdraw/src/x11/draw.c (288 lines, 9.9 KiB) -rw-r--r-- file download

ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
0
// Copyright (C) 2024, Jakob Wakeling
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
1
// All rights reserved.
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
2
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
3
#include "../draw.h"
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
4
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
5
#include <xcb/xcb.h>
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
6
#include <xcb/xcb_keysyms.h>
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
7
#include <xcb/xproto.h>
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
8
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
9
#include <stdint.h>
0db5818 Jakob Wakeling 2024-03-10 23:32:36
10
#include <stdio.h>
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
11
#include <stdlib.h>
0db5818 Jakob Wakeling 2024-03-10 23:32:36
12
#include <string.h>
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
13
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
14
enum : xcb_atom_t {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
15
	ATOM_REPAINT = 0x0f00,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
16
};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
17
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
18
struct keymap { xcb_keysym_t keysym; draw_key_k key; };
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
19
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
20
struct draw_window_s {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
21
	xcb_connection_t *connection;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
22
	xcb_screen_t *screen;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
23
	xcb_window_t window;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
24
	xcb_key_symbols_t *symbols;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
25
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
26
	uint32_t x, y, w, h;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
27
};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
28
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
29
extern const struct keymap keymap[];
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
30
extern const size_t keymap_size;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
31
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
32
static inline draw_mod_k mod(uint16_t state);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
33
static inline draw_key_k keymap_find(draw_window *window, xcb_keycode_t keycode);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
34
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
35
int draw_window_init(draw_window **window, int32_t w, int32_t h, const char *title, uint32_t flags) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
36
	(*window) = calloc(1, sizeof(draw_window)); if ((*window) == NULL) { return -1; }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
37
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
38
	(*window)->connection = xcb_connect(NULL, NULL);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
39
	if (xcb_connection_has_error((*window)->connection)) { return -1; }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
40
0db5818 Jakob Wakeling 2024-03-10 23:32:36
41
	xcb_void_cookie_t cookie;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
42
	xcb_generic_error_t *error = NULL;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
43
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
44
	(*window)->screen = xcb_setup_roots_iterator(xcb_get_setup((*window)->connection)).data;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
45
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
46
	(*window)->window = xcb_generate_id((*window)->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
47
	if ((*window)->window == -1) { xcb_disconnect((*window)->connection); return -1; }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
48
62f7b77 Jakob Wakeling 2024-03-16 18:12:38
49
	uint32_t mask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
50
	uint32_t values[4] = {
62f7b77 Jakob Wakeling 2024-03-16 18:12:38
51
		0, 0,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
52
		XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS |
62f7b77 Jakob Wakeling 2024-03-16 18:12:38
53
		XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_EXPOSURE |
62f7b77 Jakob Wakeling 2024-03-16 18:12:38
54
		XCB_EVENT_MASK_STRUCTURE_NOTIFY, XCB_VISUAL_CLASS_TRUE_COLOR
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
55
	};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
56
0db5818 Jakob Wakeling 2024-03-10 23:32:36
57
	/**/
0db5818 Jakob Wakeling 2024-03-10 23:32:36
58
	xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator((*window)->screen);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
59
	xcb_visualtype_t *visual = NULL;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
60
0db5818 Jakob Wakeling 2024-03-10 23:32:36
61
	for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
0db5818 Jakob Wakeling 2024-03-10 23:32:36
62
		if (depth_iter.data->depth != 32) continue;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
63
		xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
64
		for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
0db5818 Jakob Wakeling 2024-03-10 23:32:36
65
			visual = visual_iter.data;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
66
			break;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
67
		}
0db5818 Jakob Wakeling 2024-03-10 23:32:36
68
		if (visual != NULL) break;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
69
	}
0db5818 Jakob Wakeling 2024-03-10 23:32:36
70
0db5818 Jakob Wakeling 2024-03-10 23:32:36
71
	if (visual == NULL) { xcb_disconnect((*window)->connection); return -1; }
0db5818 Jakob Wakeling 2024-03-10 23:32:36
72
0db5818 Jakob Wakeling 2024-03-10 23:32:36
73
	xcb_colormap_t colormap = xcb_generate_id((*window)->connection);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
74
	cookie = xcb_create_colormap(
0db5818 Jakob Wakeling 2024-03-10 23:32:36
75
		(*window)->connection, XCB_COLORMAP_ALLOC_NONE, colormap, (*window)->screen->root, visual->visual_id
0db5818 Jakob Wakeling 2024-03-10 23:32:36
76
	);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
77
	error = xcb_request_check((*window)->connection, cookie);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
78
	if (error != NULL) {
0db5818 Jakob Wakeling 2024-03-10 23:32:36
79
		printf("Error %d while creating colormap\n", error->error_code);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
80
		free(error); xcb_disconnect((*window)->connection); return -1;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
81
	}
0db5818 Jakob Wakeling 2024-03-10 23:32:36
82
0db5818 Jakob Wakeling 2024-03-10 23:32:36
83
	values[3] = colormap;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
84
0db5818 Jakob Wakeling 2024-03-10 23:32:36
85
	cookie = xcb_create_window_checked(
0db5818 Jakob Wakeling 2024-03-10 23:32:36
86
		(*window)->connection, 32, (*window)->window, (*window)->screen->root, 0, 0, w, h, 0,
0db5818 Jakob Wakeling 2024-03-10 23:32:36
87
		XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visual_id, mask, values
0db5818 Jakob Wakeling 2024-03-10 23:32:36
88
	);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
89
	error = xcb_request_check((*window)->connection, cookie);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
90
	if (error != NULL) {
0db5818 Jakob Wakeling 2024-03-10 23:32:36
91
		printf("Error %d while creating window\n", error->error_code);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
92
		free(error); xcb_disconnect((*window)->connection); return -1;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
93
	}
0db5818 Jakob Wakeling 2024-03-10 23:32:36
94
0db5818 Jakob Wakeling 2024-03-10 23:32:36
95
	xcb_change_property(
0db5818 Jakob Wakeling 2024-03-10 23:32:36
96
		(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
0db5818 Jakob Wakeling 2024-03-10 23:32:36
97
		strlen(title), title
0db5818 Jakob Wakeling 2024-03-10 23:32:36
98
	);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
99
0db5818 Jakob Wakeling 2024-03-10 23:32:36
100
	xcb_change_property(
0db5818 Jakob Wakeling 2024-03-10 23:32:36
101
		(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8,
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
102
		strlen(title), title
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
103
	);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
104
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
105
	(*window)->symbols = xcb_key_symbols_alloc((*window)->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
106
	(*window)->w = w; (*window)->h = h;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
107
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
108
	xcb_map_window((*window)->connection, (*window)->window);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
109
	xcb_flush((*window)->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
110
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
111
	return 0;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
112
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
113
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
114
void draw_window_free(draw_window **window) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
115
	if (*window == NULL) { return; }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
116
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
117
	xcb_key_symbols_free((*window)->symbols);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
118
	xcb_destroy_window((*window)->connection, (*window)->window);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
119
	xcb_disconnect((*window)->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
120
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
121
	free(*window); *window = NULL;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
122
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
123
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
124
draw_event draw_window_event(draw_window *window) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
125
	xcb_generic_event_t *_e = xcb_wait_for_event(window->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
126
	if (_e == NULL) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
127
		if (draw_debug) { printf("xcb_wait_for_event returned NULL\n"); }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
128
		return (draw_event){ .kind = DRAW_EVENT_EXIT };
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
129
	}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
130
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
131
	draw_event event = {};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
132
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
133
	/* TODO handle modifiers */
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
134
	switch (_e->response_type  & ~0x80) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
135
		case XCB_KEY_PRESS: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
136
			xcb_key_press_event_t *e = (xcb_key_press_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
137
			if (draw_debug_verbose) { printf("KeyPress (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
138
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
139
			event = (draw_event){ .kind = DRAW_EVENT_KEY, .key = {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
140
				.code = keymap_find(window, e->detail), .modifiers = mod(e->state), .direction = DRAW_PRESS,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
141
			}};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
142
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
143
		case XCB_KEY_RELEASE: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
144
			xcb_key_release_event_t *e = (xcb_key_release_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
145
			if (draw_debug_verbose) { printf("KeyRelease (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
146
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
147
			event = (draw_event){ .kind = DRAW_EVENT_KEY, .key = {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
148
				.code = keymap_find(window, e->detail), .modifiers = mod(e->state), .direction = DRAW_RELEASE,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
149
			}};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
150
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
151
		case XCB_BUTTON_PRESS: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
152
			xcb_button_press_event_t *e = (xcb_button_press_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
153
			if (draw_debug_verbose) { printf("ButtonPress (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
154
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
155
			event = (draw_event){ .kind = DRAW_EVENT_MOUSE, .mouse = {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
156
				.x = e->event_x, .y = e->event_y, .button = e->detail, .modifiers = mod(e->state),
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
157
				.direction = DRAW_PRESS,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
158
			}};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
159
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
160
		case XCB_BUTTON_RELEASE: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
161
			xcb_button_release_event_t *e = (xcb_button_release_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
162
			if (draw_debug_verbose) { printf("ButtonRelease (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
163
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
164
			event = (draw_event){ .kind = DRAW_EVENT_MOUSE, .mouse = {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
165
				.x = e->event_x, .y = e->event_y, .button = e->detail, .modifiers = mod(e->state),
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
166
				.direction = DRAW_RELEASE,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
167
			}};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
168
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
169
		case XCB_MOTION_NOTIFY: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
170
			xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
171
			if (draw_debug_verbose) { printf("MotionNotify (%d, %d)\n", e->event_x, e->event_y); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
172
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
173
			event = (draw_event){ .kind = DRAW_EVENT_MOUSE, .mouse = {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
174
				.x = e->event_x, .y = e->event_y, .button = e->detail, .modifiers = mod(e->state),
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
175
				.direction = DRAW_REPEAT,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
176
			}};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
177
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
178
		case XCB_EXPOSE: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
179
			xcb_expose_event_t *e = (xcb_expose_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
180
			if (draw_debug) { printf("Expose (%d, %d, %d, %d)\n", e->x, e->y, e->width, e->height); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
181
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
182
			event = (draw_event){ .kind = DRAW_EVENT_PAINT, .paint = { e->x, e->y, e->width, e->height }};
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
183
		} break;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
184
		case XCB_UNMAP_NOTIFY: {
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
185
			xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
186
			if (draw_debug) { printf("UnmapNotify\n"); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
187
			event = (draw_event){ .kind = DRAW_EVENT_HIDE };
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
188
		} break;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
189
		case XCB_MAP_NOTIFY: {
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
190
			xcb_map_notify_event_t *e = (xcb_map_notify_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
191
			if (draw_debug) { printf("MapNotify\n"); }
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
192
			event = (draw_event){ .kind = DRAW_EVENT_SHOW };
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
193
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
194
		case XCB_CONFIGURE_NOTIFY: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
195
			xcb_configure_notify_event_t *e = (xcb_configure_notify_event_t *)_e;
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
196
			if (draw_debug) { printf("ConfigureNotify (%d, %d, %d, %d)\n", e->x, e->y, e->width, e->height); }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
197
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
198
			if (e->width != window->w || e->height != window->h) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
199
				window->w = e->width; window->h = e->height;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
200
				event = (draw_event){ .kind = DRAW_EVENT_RESIZE, .resize = { e->width, e->height }};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
201
			}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
202
		} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
203
		case XCB_CLIENT_MESSAGE: {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
204
			xcb_client_message_event_t *e = (xcb_client_message_event_t *)_e;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
205
			switch (e->type) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
206
			case ATOM_REPAINT: {
e9e9867 Jakob Wakeling 2024-03-11 22:03:59
207
				if (draw_debug) { printf("ClientMessage (REPAINT)\n"); }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
208
				event = (draw_event){ .kind = DRAW_EVENT_PAINT, .paint = { 0, 0, window->w, window->h }};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
209
			} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
210
			}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
211
		} break;
0db5818 Jakob Wakeling 2024-03-10 23:32:36
212
		default: { if (draw_debug) {
0db5818 Jakob Wakeling 2024-03-10 23:32:36
213
			printf("Unhandled X11 event: %d ", _e->response_type & ~0x80);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
214
			printf("Sequence: %u ", _e->sequence);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
215
			printf("Full sequence: %u ", _e->full_sequence);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
216
			printf("Pad0: %u ", _e->pad0);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
217
			printf("Pad: %u\n", *_e->pad);
0db5818 Jakob Wakeling 2024-03-10 23:32:36
218
		}} break;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
219
	}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
220
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
221
	free(_e); return event;
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
222
}
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
223
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
224
void draw_window_set_title(draw_window *window, const char *title) {
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
225
	xcb_change_property(
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
226
		window->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(title),
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
227
		title
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
228
	);
0c1b980 Jakob Wakeling 2024-03-16 11:36:25
229
	xcb_flush(window->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
230
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
231
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
232
void draw_window_repaint(draw_window *window) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
233
	xcb_client_message_event_t e = {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
234
		.response_type = XCB_CLIENT_MESSAGE, .format = 32, .window = window->window, .type = ATOM_REPAINT,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
235
		.data.data32 = {}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
236
	};
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
237
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
238
	xcb_send_event(window->connection, 0, window->window, XCB_EVENT_MASK_NO_EVENT, (const char *)&e);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
239
	xcb_flush(window->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
240
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
241
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
242
int draw_window_draw(draw_window *w, point dp, draw_buffer *buf, rect br) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
243
	if (w == NULL) { return 1; }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
244
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
245
	xcb_gcontext_t gc = xcb_generate_id(w->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
246
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
247
	xcb_create_gc(w->connection, gc, w->window, 0, NULL);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
248
	xcb_put_image(
0db5818 Jakob Wakeling 2024-03-10 23:32:36
249
		w->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, w->window, gc, br.w, br.h, dp.x, dp.y, 0, 32,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
250
		(buf->bounds.w * buf->bounds.h) * sizeof (*buf->buf), (uint8_t *)buf->buf
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
251
	);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
252
	xcb_free_gc(w->connection, gc);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
253
	xcb_flush(w->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
254
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
255
	return 0;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
256
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
257
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
258
void draw_window_clear(draw_window *w, uint32_t colour) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
259
	if (w == NULL) { return; }
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
260
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
261
	xcb_gcontext_t gc = xcb_generate_id(w->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
262
	xcb_create_gc(w->connection, gc, w->window, 0, NULL);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
263
	xcb_change_gc(w->connection, gc, XCB_GC_FOREGROUND, (uint32_t[]){colour});
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
264
	xcb_poly_fill_rectangle(w->connection, w->window, gc, 1, (xcb_rectangle_t[]){{
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
265
		.x = 0, .y = 0, .width = w->w, .height = w->h,
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
266
	}});
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
267
	xcb_free_gc(w->connection, gc);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
268
	xcb_flush(w->connection);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
269
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
270
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
271
static inline draw_mod_k mod(uint16_t state) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
272
	draw_mod_k mod = 0;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
273
	mod |= ((state & XCB_MOD_MASK_SHIFT) != 0) * DRAW_MOD_SHIFT;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
274
	mod |= ((state & XCB_MOD_MASK_CONTROL) != 0) * DRAW_MOD_CONTROL;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
275
	mod |= ((state & XCB_MOD_MASK_1) != 0) * DRAW_MOD_ALT;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
276
	mod |= ((state & XCB_MOD_MASK_4) != 0) * DRAW_MOD_SUPER;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
277
	mod |= ((state & XCB_MOD_MASK_LOCK) != 0) * DRAW_MOD_CAPS_LOCK;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
278
	mod |= ((state & XCB_MOD_MASK_2) != 0) * DRAW_MOD_NUM_LOCK;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
279
	return mod;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
280
}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
281
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
282
static inline draw_key_k keymap_find(draw_window *window, xcb_keycode_t keycode) {
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
283
	xcb_keysym_t keysym = xcb_key_symbols_get_keysym(window->symbols, keycode, 0);
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
284
	for (size_t i = 0; i < keymap_size; i += 1) { if (keymap[i].keysym == keysym) { return keymap[i].key; }}
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
285
	return DRAW_KEY_UNKNOWN;
ccd60e6 Jakob Wakeling 2024-03-10 19:35:51
286
}
287