diff --git a/Makefile b/Makefile index 405effe..9a9d0dc 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/main.c b/main.c index f811a1f..d7880fc 100644 --- a/main.c +++ b/main.c @@ -198,6 +198,8 @@ 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; @@ -205,10 +207,6 @@ static inline void _apply_default_conf(void) { #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__ diff --git a/utils/config.c b/utils/config.c index 12bf977..60022b6 100644 --- a/utils/config.c +++ b/utils/config.c @@ -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 { @@ -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"); diff --git a/utils/config.h b/utils/config.h index e4a2b9b..4cdab6b 100644 --- a/utils/config.h +++ b/utils/config.h @@ -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; /* diff --git a/utils/utils.c b/utils/utils.c index aab42bc..ea64315 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -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 @@ -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; } diff --git a/xscreenshot/xscreenshot.c b/xscreenshot/xscreenshot.c index abe44b7..f925ec5 100644 --- a/xscreenshot/xscreenshot.c +++ b/xscreenshot/xscreenshot.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include /* LSBFirst: BGRA -> RGBA */ @@ -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; @@ -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); diff --git a/xscreenshot/xscreenshot.h b/xscreenshot/xscreenshot.h index 04f439b..f0c71e7 100644 --- a/xscreenshot/xscreenshot.h +++ b/xscreenshot/xscreenshot.h @@ -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_