From 36cb48c65052ff2b3735418f0cd7813bf82386bf Mon Sep 17 00:00:00 2001 From: hkc Date: Wed, 5 Jun 2024 23:19:03 +0300 Subject: [PATCH] Taking screenshot of one window by ID TODO: iterate over entire tree and take separate screenshots of each window --- img/scrall/.gitignore | 1 + img/scrall/Makefile | 12 ++++++ img/scrall/main.c | 85 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 img/scrall/.gitignore create mode 100644 img/scrall/Makefile create mode 100644 img/scrall/main.c diff --git a/img/scrall/.gitignore b/img/scrall/.gitignore new file mode 100644 index 0000000..31adcbb --- /dev/null +++ b/img/scrall/.gitignore @@ -0,0 +1 @@ +scrall diff --git a/img/scrall/Makefile b/img/scrall/Makefile new file mode 100644 index 0000000..7aa5402 --- /dev/null +++ b/img/scrall/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -Wall -Wextra `exec pkg-config --cflags raylib xcb xcb-composite` +LDFLAGS := -lm `pkg-config --libs raylib xcb xcb-composite` + +scrall: main.c + $(CC) $(CFLAGS) main.c $(LDFLAGS) -o scrall + + +clean: + $(RM) scrall + +run: scrall + ./scrall diff --git a/img/scrall/main.c b/img/scrall/main.c new file mode 100644 index 0000000..9a254fd --- /dev/null +++ b/img/scrall/main.c @@ -0,0 +1,85 @@ +// x-run: make run +#include +#include +#include +#include +#include +#include +#include + + +Image get_screenshot(xcb_connection_t *conn, xcb_window_t wid); + +int main(int argc, char **argv) { + xcb_connection_t *xcb = xcb_connect(NULL, NULL); + + SetConfigFlags(FLAG_WINDOW_TRANSPARENT); + InitWindow(0, 0, "img/scrall"); + + + Image screenshot = get_screenshot(xcb, 50331654); + assert(screenshot.width > 0); + + Texture2D screenshot_tex = LoadTextureFromImage(screenshot); + SetWindowSize(screenshot.width, screenshot.height); + + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(BLANK); + DrawTexture(screenshot_tex, 0, 0, WHITE); + EndDrawing(); + } +} + +Image get_screenshot(xcb_connection_t *conn, xcb_window_t wid) { + xcb_generic_error_t *err = NULL; + + xcb_composite_redirect_window(conn, wid, XCB_COMPOSITE_REDIRECT_AUTOMATIC); + + xcb_get_geometry_cookie_t gg_cookie = xcb_get_geometry(conn, wid); + xcb_get_geometry_reply_t *gg_reply = xcb_get_geometry_reply(conn, gg_cookie, &err); + + if (!gg_reply) { + fprintf(stderr, "xcb: error: geometry: %d\n", err->error_code); + return (Image){ + .data = err, .width = 0, .height = 0, .format = 0, .mipmaps = 0 + }; + } + + int win_w = gg_reply->width; + int win_h = gg_reply->height; + assert(gg_reply->depth == 32); + fprintf(stderr, "width: %d\nheight: %d\n", win_w, win_h); + + free(gg_reply); + + xcb_pixmap_t win_pixmap = xcb_generate_id(conn); + xcb_composite_name_window_pixmap(conn, wid, win_pixmap); + + xcb_get_image_cookie_t gi_cookie = xcb_get_image(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, win_pixmap, 0, 0, win_w, win_h, (uint32_t)(~0UL)); + xcb_get_image_reply_t *gi_reply = xcb_get_image_reply(conn, gi_cookie, &err); + if (!gi_reply) { + fprintf(stderr, "xcb: error: get_image_reply: %d\n", err->error_code); + return (Image){ + .data = err, .width = 0, .height = 0, .format = 0, .mipmaps = 0 + }; + } + + int data_len = xcb_get_image_data_length(gi_reply); + fprintf(stderr, "data_len: %d\n", data_len); + + uint8_t *data = xcb_get_image_data(gi_reply); + + Image img = GenImageColor(win_w, win_h, BLANK); + + for (int i = 0; i < data_len; i += 4) { + ((uint8_t *)img.data)[i + 0] = data[i + 2]; + ((uint8_t *)img.data)[i + 1] = data[i + 1]; + ((uint8_t *)img.data)[i + 2] = data[i + 0]; + ((uint8_t *)img.data)[i + 3] = data[i + 3]; + } + + free(gi_reply); + + return img; +}