Skip to content

Commit

Permalink
Implement get screenshot of selected display for Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
thevindu-w committed May 12, 2024
1 parent 3fbe20b commit bd94d13
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ ifeq ($(detected_OS),Linux)
OBJS+= xclip/xclip.o xclip/xclib.o xscreenshot/xscreenshot.o
CFLAGS+= -ftree-vrp -Wformat-signedness -Wshift-overflow=2 -Wstringop-overflow=4 -Walloc-zero -Wduplicated-branches -Wduplicated-cond -Wtrampolines -Wjump-misses-init -Wlogical-op -Wvla-larger-than=65536
CFLAGS_OPTIM=-Os
LDLIBS=-lunistring -lssl -lcrypto -lX11 -lXmu -lpng
LDLIBS=-lunistring -lssl -lcrypto -lX11 -lXmu -lxcb -lxcb-randr -lpng
LINK_FLAGS_BUILD=-no-pie -Wl,-s,--gc-sections
else ifeq ($(detected_OS),Windows)
OBJS+= utils/win_image.o
Expand Down
6 changes: 2 additions & 4 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,15 @@ static inline void _apply_default_conf(void) {
if (configuration.max_text_length <= 0) configuration.max_text_length = MAX_TEXT_LENGTH;
if (configuration.max_file_size <= 0) configuration.max_file_size = MAX_FILE_SIZE;
if (configuration.cut_sent_files < 0) configuration.cut_sent_files = 0;
if (configuration.client_selects_display < 0) configuration.client_selects_display = 0;
if (configuration.display <= 0) configuration.display = 1;
#ifdef WEB_ENABLED
if (configuration.web_port <= 0) configuration.web_port = WEB_PORT;
if (configuration.web_mode_enabled < 0) configuration.web_mode_enabled = 0;
#endif
#ifdef _WIN32
if (configuration.tray_icon < 0) configuration.tray_icon = 1;
#endif
#if defined(_WIN32) || defined(__APPLE__)
if (configuration.client_selects_display < 0) configuration.client_selects_display = 0;
if (configuration.display <= 0) configuration.display = 1;
#endif
}

#ifdef __linux__
Expand Down
14 changes: 5 additions & 9 deletions utils/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,15 +288,13 @@ static void parse_line(char *line, config *cfg) {
set_int64(value, &(cfg->max_file_size));
} else if (!strcmp("cut_sent_files", key)) {
set_is_true(value, &(cfg->cut_sent_files));
#ifdef _WIN32
} else if (!strcmp("tray_icon", key)) {
set_is_true(value, &(cfg->tray_icon));
#endif
#if defined(_WIN32) || defined(__APPLE__)
} else if (!strcmp("client_selects_display", key)) {
set_is_true(value, &(cfg->client_selects_display));
} else if (!strcmp("display", key)) {
set_ushort(value, &(cfg->display));
#ifdef _WIN32
} else if (!strcmp("tray_icon", key)) {
set_is_true(value, &(cfg->tray_icon));
#endif
#ifdef DEBUG_MODE
} else {
Expand Down Expand Up @@ -328,12 +326,10 @@ void parse_conf(config *cfg, const char *file_name) {
cfg->max_text_length = 0;
cfg->max_file_size = 0;
cfg->cut_sent_files = -1;
#ifdef _WIN32
cfg->tray_icon = -1;
#endif
#if defined(_WIN32) || defined(__APPLE__)
cfg->client_selects_display = -1;
cfg->display = 0;
#ifdef _WIN32
cfg->tray_icon = -1;
#endif
if (ipv4_aton(NULL, &(cfg->bind_addr)) != EXIT_SUCCESS) error_exit("Error initializing bind address");

Expand Down
6 changes: 2 additions & 4 deletions utils/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,12 @@ typedef struct _config {
uint32_t max_text_length;
int64_t max_file_size;
char cut_sent_files;
char client_selects_display;
unsigned short display;

#ifdef _WIN32
char tray_icon;
#endif
#if defined(_WIN32) || defined(__APPLE__)
char client_selects_display;
unsigned short display;
#endif
} config;

/*
Expand Down
4 changes: 2 additions & 2 deletions utils/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,6 @@ int put_clipboard_text(char *data, size_t len) {
}

int get_image(char **buf_ptr, size_t *len_ptr, int mode, int disp) {
(void)disp;
*buf_ptr = NULL;

// Try to get copied image unless the mode is screenshot only
Expand All @@ -844,8 +843,9 @@ int get_image(char **buf_ptr, size_t *len_ptr, int mode, int disp) {
*buf_ptr = NULL;
*len_ptr = 0;

if (disp <= 0 || !configuration.client_selects_display) disp = (int)configuration.display;
// Try to get screenshot unless the mode is copied image only
if (mode != IMG_COPIED_ONLY && screenshot_util(len_ptr, buf_ptr) == EXIT_SUCCESS &&
if (mode != IMG_COPIED_ONLY && screenshot_util(disp, len_ptr, buf_ptr) == EXIT_SUCCESS &&
*len_ptr > 8) { // do not change the order
return EXIT_SUCCESS;
}
Expand Down
53 changes: 49 additions & 4 deletions xscreenshot/xscreenshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <stdlib.h>
#include <string.h>
#include <utils/utils.h>
#include <xcb/randr.h>
#include <xcb/xcb.h>
#include <xscreenshot/xscreenshot.h>

/* LSBFirst: BGRA -> RGBA */
Expand Down Expand Up @@ -102,11 +104,55 @@ static int png_write_buf(XImage *img, char **buf_ptr, size_t *len) {
return EXIT_SUCCESS;
}

int screenshot_util(size_t *len, char **buf) {
int screenshot_util(int display, size_t *len, char **buf) {
xcb_connection_t *dsp = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(dsp)) {
*len = 0;
return EXIT_FAILURE;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waggregate-return"
xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(dsp)).data->root;
xcb_randr_get_monitors_cookie_t cookie = xcb_randr_get_monitors(dsp, root, 1);
#pragma GCC diagnostic pop
xcb_randr_get_monitors_reply_t *reply = xcb_randr_get_monitors_reply(dsp, cookie, NULL);
int cnt = xcb_randr_get_monitors_monitors_length(reply);
if (display > cnt) {
free(reply);
xcb_disconnect(dsp);
*len = 0;
return EXIT_FAILURE;
}

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waggregate-return"
xcb_randr_monitor_info_iterator_t itr = xcb_randr_get_monitors_monitors_iterator(reply);
#pragma GCC diagnostic pop

int x = 0, y = 0;
unsigned int width = 0, height = 0;
while (itr.rem) {
display--;
if (display == 0) {
xcb_randr_monitor_info_t *info = itr.data;
x = info->x;
y = info->y;
width = info->width;
height = info->height;
break;
}
xcb_randr_monitor_info_next(&itr);
}
free(reply);
xcb_disconnect(dsp);
if (width == 0 || height == 0) {
*len = 0;
return EXIT_FAILURE;
}

XImage *img;
Display *dpy;
Window win;
XWindowAttributes attr;

if (!(dpy = XOpenDisplay(NULL))) {
*len = 0;
Expand All @@ -116,9 +162,8 @@ int screenshot_util(size_t *len, char **buf) {
win = RootWindow(dpy, 0);

XGrabServer(dpy);
XGetWindowAttributes(dpy, win, &attr);

img = XGetImage(dpy, win, 0, 0, (unsigned int)(attr.width), (unsigned int)(attr.height), 0xffffffff, ZPixmap);
img = XGetImage(dpy, win, x, y, width, height, AllPlanes, ZPixmap);

XUngrabServer(dpy);
XCloseDisplay(dpy);
Expand Down
2 changes: 1 addition & 1 deletion xscreenshot/xscreenshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
* Returns 0 on success.
* Returns -1 if an error occured.
*/
extern int screenshot_util(size_t *len_p, char **buf_p);
extern int screenshot_util(int display, size_t *len_p, char **buf_p);

#endif // XSCREENSHOT_XSCREENSHOT_H_

0 comments on commit bd94d13

Please sign in to comment.