libdraw

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

AuthorJakob Wakeling <[email protected]>
Date2024-03-10 10:32:36
Commit0db58180873b28d900e54d2db51566fcc05ab1d5
Parent345d96ccfc7061d28302d386dcee06bbac35fd53

Use a 32 bit pixel depth instead of 24

Diffstat

M examples/draw.c | 20 ++++++++++----------
M src/x11/draw.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----

2 files changed, 73 insertions, 15 deletions

diff --git a/examples/draw.c b/examples/draw.c
index 623e0f0..47b7289 100644
--- a/examples/draw.c
+++ b/examples/draw.c
@@ -3,19 +3,19 @@
 int main() {
 	draw_debug = true;
 	draw_window *window; int32_t w = 800, h = 600;
-	draw_window_init(&window, w, h, "Draw", 0);
+	if (draw_window_init(&window, w, h, "Draw", 0) == -1) { return -1; }
 
 	bool left = false, right = false, draw = false;
-	uint32_t colour = 0x00ff0000;
+	uint32_t colour = 0xffff0000;
 
 	draw_buffer *buf = draw_buffer_init(w, h);
-	draw_buffer_clear(buf, 0x00000000);
+	draw_buffer_clear(buf, 0xff000000);
 
 	for (draw_event e; (e = draw_window_event(window)).kind != DRAW_EVENT_EXIT;) switch (e.kind) {
 	case DRAW_EVENT_KEY:    {
-		if (e.key.code == DRAW_KEY_1) { colour = 0x00ff0000; }
-		if (e.key.code == DRAW_KEY_2) { colour = 0x0000ff00; }
-		if (e.key.code == DRAW_KEY_3) { colour = 0x000000ff; }
+		if (e.key.code == DRAW_KEY_1) { colour = 0xffff0000; }
+		if (e.key.code == DRAW_KEY_2) { colour = 0xff00ff00; }
+		if (e.key.code == DRAW_KEY_3) { colour = 0xff0000ff; }
 	} break;
 	case DRAW_EVENT_MOUSE:  {
 		if (e.mouse.button == DRAW_MOUSE_LEFT) {
@@ -28,10 +28,10 @@ int main() {
 		}
 
 		if (left) { draw_buffer_rect(buf, (point){e.mouse.x, e.mouse.y}, (rect){-5, -5, 6, 6}, colour); }
-		if (right) { draw_buffer_rect(buf, (point){e.mouse.x, e.mouse.y}, (rect){-5, -5, 6, 6}, 0x00000000); }
-		if ((left || right) && !draw) { draw_window_repaint(window); }
+		if (right) { draw_buffer_rect(buf, (point){e.mouse.x, e.mouse.y}, (rect){-5, -5, 6, 6}, 0xff000000); }
+		if ((left || right) && !draw) { goto redraw; /*draw_window_repaint(window);*/ }
 	} break;
-	case DRAW_EVENT_PAINT:  {
+	case DRAW_EVENT_PAINT: redraw: {
 		draw_window_draw(window, (point){0, 0}, buf, buf->bounds); draw = false;
 	} break;
 	case DRAW_EVENT_RESIZE: {
@@ -39,7 +39,7 @@ int main() {
 
 		draw_buffer *old = buf;
 		buf = draw_buffer_init(w, h);
-		draw_buffer_clear(buf, 0x00000000);
+		draw_buffer_clear(buf, 0xff000000);
 		draw_buffer_copy(buf, old, (point){0, 0}, old->bounds);
 		draw_buffer_free(&old);
 	} break;
diff --git a/src/x11/draw.c b/src/x11/draw.c
index bbe3365..d1607db 100644
--- a/src/x11/draw.c
+++ b/src/x11/draw.c
@@ -8,8 +8,9 @@
 #include <xcb/xproto.h>
 
 #include <stdint.h>
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 enum : xcb_atom_t {
 	ATOM_REPAINT = 0x0f00,
@@ -38,21 +39,68 @@ int draw_window_init(draw_window **window, int32_t w, int32_t h, const char *tit
 	(*window)->connection = xcb_connect(NULL, NULL);
 	if (xcb_connection_has_error((*window)->connection)) { return -1; }
 
+	xcb_void_cookie_t cookie;
+	xcb_generic_error_t *error = NULL;
+
 	(*window)->screen = xcb_setup_roots_iterator(xcb_get_setup((*window)->connection)).data;
 
 	(*window)->window = xcb_generate_id((*window)->connection);
 	if ((*window)->window == -1) { xcb_disconnect((*window)->connection); return -1; }
 
-	uint32_t mask = XCB_CW_EVENT_MASK;
-	uint32_t values[1] = {
+	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
+	uint32_t values[4] = {
+		0xff000000, 0,
 		XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS |
 		XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
 		XCB_EVENT_MASK_BUTTON_MOTION
 	};
 
-	xcb_create_window(
-		(*window)->connection, XCB_COPY_FROM_PARENT, (*window)->window, (*window)->screen->root, 0, 0, w, h, 0,
-		XCB_WINDOW_CLASS_INPUT_OUTPUT, (*window)->screen->root_visual, mask, values
+	/**/
+	xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator((*window)->screen);
+	xcb_visualtype_t *visual = NULL;
+
+	for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
+		if (depth_iter.data->depth != 32) continue;
+		xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+		for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
+			visual = visual_iter.data;
+			break;
+		}
+		if (visual != NULL) break;
+	}
+
+	if (visual == NULL) { xcb_disconnect((*window)->connection); return -1; }
+
+	xcb_colormap_t colormap = xcb_generate_id((*window)->connection);
+	cookie = xcb_create_colormap(
+		(*window)->connection, XCB_COLORMAP_ALLOC_NONE, colormap, (*window)->screen->root, visual->visual_id
+	);
+	error = xcb_request_check((*window)->connection, cookie);
+	if (error != NULL) {
+		printf("Error %d while creating colormap\n", error->error_code);
+		free(error); xcb_disconnect((*window)->connection); return -1;
+	}
+
+	values[3] = colormap;
+
+	cookie = xcb_create_window_checked(
+		(*window)->connection, 32, (*window)->window, (*window)->screen->root, 0, 0, w, h, 0,
+		XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visual_id, mask, values
+	);
+	error = xcb_request_check((*window)->connection, cookie);
+	if (error != NULL) {
+		printf("Error %d while creating window\n", error->error_code);
+		free(error); xcb_disconnect((*window)->connection); return -1;
+	}
+
+	xcb_change_property(
+		(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
+		strlen(title), title
+	);
+
+	xcb_change_property(
+		(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8,
+		strlen("libdraw"), "libdraw"
 	);
 
 	(*window)->symbols = xcb_key_symbols_alloc((*window)->connection);
@@ -140,7 +188,13 @@ draw_event draw_window_event(draw_window *window) {
 			} break;
 			}
 		} break;
-		default: { if (draw_debug) { printf("Unhandled X11 event: %d\n", _e->response_type & ~0x80); }} break;
+		default: { if (draw_debug) {
+			printf("Unhandled X11 event: %d ", _e->response_type & ~0x80);
+			printf("Sequence: %u ", _e->sequence);
+			printf("Full sequence: %u ", _e->full_sequence);
+			printf("Pad0: %u ", _e->pad0);
+			printf("Pad: %u\n", *_e->pad);
+		}} break;
 	}
 
 	free(_e); return event;
@@ -161,10 +215,9 @@ int draw_window_draw(draw_window *w, point dp, draw_buffer *buf, rect br) {
 
 	xcb_gcontext_t gc = xcb_generate_id(w->connection);
 
-
 	xcb_create_gc(w->connection, gc, w->window, 0, NULL);
 	xcb_put_image(
-		w->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, w->window, gc, br.w, br.h, dp.x, dp.y, 0, 24,
+		w->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, w->window, gc, br.w, br.h, dp.x, dp.y, 0, 32,
 		(buf->bounds.w * buf->bounds.h) * sizeof (*buf->buf), (uint8_t *)buf->buf
 	);
 	xcb_free_gc(w->connection, gc);