things/img/scrall/screenshot.c

69 lines
2.1 KiB
C

#include "screenshot.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <xcb/composite.h>
#include <xcb/xcb_errors.h>
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 (wid: 0x%08x)\n", err->error_code, wid);
return (Image){
.data = 0, .width = 0, .height = 0, .format = 0, .mipmaps = 0
};
}
int win_w = gg_reply->width;
int win_h = gg_reply->height;
int win_d = gg_reply->depth;
assert(win_d == 32 || win_d == 24);
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 (wid: 0x%08x)\n", err->error_code, wid);
return (Image){
.data = 0, .width = 0, .height = 0, .format = 0, .mipmaps = 0
};
}
int data_len = xcb_get_image_data_length(gi_reply);
uint8_t *data = xcb_get_image_data(gi_reply);
Image img = GenImageColor(win_w, win_h, BLANK);
if (win_d == 24) {
for (int i = 0; i < data_len / 3; i++) {
((uint8_t *)img.data)[i * 4 + 0] = data[i * 3 + 2];
((uint8_t *)img.data)[i * 4 + 1] = data[i * 3 + 1];
((uint8_t *)img.data)[i * 4 + 2] = data[i * 3 + 0];
((uint8_t *)img.data)[i * 4 + 3] = 0xff;
}
} else {
for (int i = 0; i < data_len / 4; i++) {
((uint8_t *)img.data)[i * 4 + 0] = data[i * 4 + 2];
((uint8_t *)img.data)[i * 4 + 1] = data[i * 4 + 1];
((uint8_t *)img.data)[i * 4 + 2] = data[i * 4 + 0];
((uint8_t *)img.data)[i * 4 + 3] = data[i * 4 + 3];
}
}
free(gi_reply);
return img;
}