From patchwork Wed Feb 10 17:15:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sgerwk-at-aol.com@ffmpeg.org X-Patchwork-Id: 25556 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a5b:101:0:0:0:0:0 with SMTP id 1csp1386135ybx; Wed, 10 Feb 2021 09:15:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJzJzINZXuNEOO2f5GYS8RIkc6UeYpSNIpOj0g8+jLqOI8tasiqn7g7S2WzCQ7bl3o2sSsTK X-Received: by 2002:a17:906:c318:: with SMTP id s24mr3907210ejz.187.1612977333118; Wed, 10 Feb 2021 09:15:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1612977333; cv=none; d=google.com; s=arc-20160816; b=nOg5r9j85o8h28J+RGLtezH/fgKm30dJ+x6bOqDbQnUY9N9YPOtWcMnTTSGofVumEi p0RmVUmyzR+AmnZtgElkYAfSOoNeGzFmxG98/qUCil7whlAGezEwfSHy5KuDPra/FaKc QF6DMIoYD9IHJeOqpH4jKR2koTIVj3sPe6iB98lrsfZXjFzVfmyCbm4zVdrRcNHJTRAk MEU3fD1kdmlw5jmpx2DyceAp6BPIaHcOS2Q7rmEUrAij7cABM+zNOnWnJnIxTyFLWobF 0OaEuQ3ho8XUOsI+5rrffIqriTo+yeQk7YhdfN18a1sI47kSCgUv4pnbtndG1dr8e6Co bnWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:message-id:in-reply-to:to:from:date :dkim-signature:delivered-to; bh=wsUbfqOqWwFCwogh0UJVI/i+JKasGAUeg3ruzp+td60=; b=dbr0Ngmb1bN2pfWRL5r+W6+cf1NQ62/BGyMwNjLqlHKV73Lc93fIb/YvlW+EId3m8+ I0du1dBJnAEyghs8spfAKm1HSm1Yg9GA3jTJ4JyAU+ijGWzsFYJZ6YMLiScp2HZaTC0T fsFZ880P3N2bRGmQ8xey9wS10poiQmujfu00kPtyI2L38QTLO5vwO8HaDqR+KRijkHd6 kYOOotQJ0B0rtBi4hnpPp3kvUZ2jH/MdKMD4umoBKfoC6on2x5AKLa1ZrR7awGscNC9e HELoqC833K60Vxi8yH7px4y6WdE4zg7kAFnaEQd2kvc/QxasN2XdWaVGDe4DpC4OkBZh kmYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@aol.com header.s=a2048 header.b=AxHUSNPl; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dm10si1810248ejc.64.2021.02.10.09.15.31; Wed, 10 Feb 2021 09:15:33 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@aol.com header.s=a2048 header.b=AxHUSNPl; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6338868A29C; Wed, 10 Feb 2021 19:15:30 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from sonic310-14.consmr.mail.bf2.yahoo.com (sonic310-14.consmr.mail.bf2.yahoo.com [74.6.135.124]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 05F1E68803A for ; Wed, 10 Feb 2021 19:15:23 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aol.com; s=a2048; t=1612977322; bh=lv8OtfPGVhYqumY6o4KPrBPTg0SKZuSQeDlurCnXxh0=; h=Date:From:To:Subject:In-Reply-To:References:From:Subject:Reply-To; b=AxHUSNPlyIGs9cqj95w8HWLPSe+2gNCfk/6yhxx+xJLDRwYsH8DdUOO9IVkN1ipabFgQpRwsrR/Xh6eR+trUJx+gcjqnuVgTgXl/Sy8nL8P8BOkftHcVXbPA+wZRSs7x2XGUzEMChytWJo8Yj4jDD5ISHfl3PanwFwfWVFjycQqLa+zS7SU2tYVzBksAbLaQzBB3cwkNYj/t7YLie0Rz28aaXs5JbYURC1avtlHnn/oM+r3g2w/ECHtV1Kvd3x+WNRd/yyzJ9ej0RsajK0xvGm6XDPAPi0GJxjkrWTjxawHQaY8uIEXEp/crJH63RHUl+OFciZll7o9NdvbuQy0wUQ== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1612977322; bh=dbQULXSjEjggSZErov7iPaLoY/vAPN+1Whc+PNxvnmF=; h=X-Sonic-MF:Date:From:To:Subject:From:Subject; b=D3G0M2apJNJxevxRF/dgKOI67MOgKtJF6KphajtslB+frfdXYFE/jxEy6qpDOYgbutiywOFij85ctpIsVxbEtNxtYnde2S9m9jpnu9M0Kpw5zoV8v6CpLOXmbLu1DrB9t18VS1hjKRGHB9lXWhfOfFC5lYLWLCXFkKp9uKk8eH7INIc1kedKvvIQ5eHqlkG5W9/5q5DYIZj+M1yB/wOaWncNRD/MvQKLyqzM4+DKmNxb22UNeghC/xCZ6NSnVL65N46s2u0VvEtqUTODqHUsdYbhTpMpm0F57gz31zpDU7g5OEHuVrs6OQuGJOREo2w7201iOV/J4fw8LiUYAkFyvQ== X-YMail-OSG: 6pLf7k4VM1kgZ2o8PbAbVQ0uQrgNE6wlWtzjyFxdHB_sMT55VkD1dsYW3eb.fMu en4sFGE76rzTkpHJPUWmAFRywBV_1HHOeFt.juHUZTlEL8dImhCBanP8idymojA2SewbhRVuOlyB r8qElmObbSUYcHlSVPTP6JmQu32BSlhrJApnJQbgLQ8k_mzz9CHbjvEzXTDg6L59z3uLMZ_bmvaY 5cnLZkGv3UUNqeeNA0B9FhJHrjS7dc.m4sCIYemuuNyMRfgLTrikReGbvXD6lbyU8VSekhvuf6eJ wRNVl4ZMI6SEDronRjTy2C7dreMAnGRmL1F4ymen9beB_pIzfROug_njqOOfkW2tmU5V8JoEiwKd sfi2VfE1bL9FpgHQvymQmtyizSc2B9jx2Afd6stZGTBRH362XkQvagUXlVTgs25wOFNPT81xHtbG LjTqCGGedHEkkGXiW1J.KNU8KjLYkh4Brfsjxe9PX4EOY1pDVTUPlSodlgCAzvS.f45BcrcFzngL FfL2X5oLQey_OP.zfsTO6zUa6.kSo9OT69Yla9fAheh_rSZ_zYhJI7Bq1n.0e_.VjGu3LDkerOMg ug4HXhegJ5YQuRAb7TaVmQOUtJAoGvfuoMf3mXzsMtYiAMrSLLAMvVYVTNoV2hDSUgGBHDHox5iN WCwZl4TmxVbZwCMhAy_gSPfPpnUBtgeROW2rguI.xF6bA_HahpSMOewS7bhrjqbknVl1wC8lhvZ_ rnhbUaTi23yqeAYNKF8MnouxeyuVVnPEG1Li7Jr6qFjYgxXRKjJKYkJt.dCpkfKCkUFDXPMUKztG f53JnCEtvYareIYX3jzjptVlGROVHqMOnuQZX_sFAQ5rFoeSNpvh5yXHKON4dJsKtFQtm4Hhea96 XWmxzYehkMIgU4k0uxVjE63HlWc.d_SZgAnIoMbXwN5KhTobtwOo4QBrdEATynX3G0EmQ5a6QZDL 7tHD6axMKajvbVv55Y3u7nr6wwJUyvPj151N2G8eWXSeLHzQEbJq1Ie3YxoQ0iSCX2eJHHzGuNpc QKI91DhsYyRcH7EUOeDgCB7U260G4ZvxYVmSUqG2vS8eNJ4gHSM6qhV0_N7LF_1NpfMM_WNjjoCF 4Q_wO_LbZuc2JPEDno6Qz.5MKDaxU4xZLXVBo5b.Kia.a8ekCWdd80oxSLuM6Um1qGZ.K404PM9A NtwOE_KJM7bnMrnMTDhnCJWqirOjfmXw1lIGs5hdaQ696uOS9OvA6n4MNPz99iyEOnB9I9j6fk9B lIu4kKUMKfEETAUNAEYiiIx1_Kd6B4ALsY3MSiEUcDj1pzwdF5KHK5ZfnnaU93ZzGK0WTS5FSKc6 tJRazFulei_1BTnXwZrypBswKbdzoZCohsq6Qz2YsZ81szBrKscQgdkLS6ptDFfTZ3HIiuUYnE2p o1WcwtPhHydBcrbLXnJWh_3Dcfg1BVy0C6ytRLgFNyv67gVUzHoXlv3EK_8ADFXGzHYuVRByFx0Y aZe5Qdf0tq5RL1KToUoGNM.mIPyJYx.QfNmQtt3rkTAWiwBbjAZgJ1_1VIT2kiL_bQgkGMttpeAG 5a3215sH4EIXur0YAKaFwCW_hZKT.L1ISyX899ZPIZ5rPHnfhKnYW6sHQ3yW0tCe315VNdXHk.7X nJB3lFN6Oej_rV5HV6sL2WEk_ey1EqbhnnPKrr0FjJOVIvbQrBVYSLjdxJsKiCYw0V2dvqneKL8A 71SjzgYJraOgfneffGTzIwJwIFC_DaEnoE77DJtib_.9uVYsFfgXPm3G70fZi6uFXTaRT03m59cV bnpwqxGTEeCEMf8DEfmjcied0S7dHE0ZfUShtdqJb.c4K43iMXxYdSvVQCQL7ttkrilq8CXaD.EE uvJI.o1JV9_Jm5ZWiS4rIigMypWQ9fLqT_qkS0KjqvAit.GXL.3LNxd.hT9SdmyMDtLLCRkHuM.X gEqe2_i9gx2dVyx3L3IhKx4svdrU0N3pkWQq5KWrj1SIktVFIf8w6FGZ6kj2UEpOv95LRH5nZxUB GU7zDxhKd8Ybe7LyAftbdkuEACNlf9_.Hf3yAQ7gVJiiApC1S6Hx_5duRT0dPqwM3FTH3bYAv8wf _MOFIOUBYlom5DuB61dCPEdMcz5_JGMXMDlx9iMB9awQ.Y4FSyFL09vZr9DAyzTysklDWwts_XKi SzVcIj2gCfVMFeyLCyRKsAtIQELQQJDE.x3KoxQJ0ESpYwA1DyEhmBDIqoM01X4VKfvcyGHMx7Lx Vg31BerICkjvD3ix_iDh7rYiz3Ajp4oGbNeYEZmdzi9ENmZF7BgK5_eLR5zj_GVtRLIfWryM5cqz dxx4qOX3w.Asp5jeHkd9DGGAISbM4c1PdVpmKjlK4kCXWot2UjUuVQKUsThvsBGLWzxlfkxfOLgu V3k0ps1EF1rfss90- X-Sonic-MF: Received: from sonic.gate.mail.ne1.yahoo.com by sonic310.consmr.mail.bf2.yahoo.com with HTTP; Wed, 10 Feb 2021 17:15:22 +0000 Received: by smtp417.mail.ir2.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID 37efc4770c6b81575c463e8b5bce7d52; Wed, 10 Feb 2021 17:15:17 +0000 (UTC) Date: Wed, 10 Feb 2021 18:15:15 +0100 (CET) From: sgerwk-at-aol.com@ffmpeg.org To: FFmpeg development discussions and patches In-Reply-To: <20210207195253.d6zm76mxigq3inkk@jackie> Message-ID: <4ef7cc3a-1d14-49e6-291d-c58ed84da898@aol.com> References: <26fa125b-357-dffb-1787-f7b14f8c667b.ref@aol.com> <26fa125b-357-dffb-1787-f7b14f8c667b@aol.com> <20210207195253.d6zm76mxigq3inkk@jackie> MIME-Version: 1.0 X-Mailer: WebService/1.1.17712 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.aol Apache-HttpAsyncClient/4.1.4 (Java/11.0.9.1) Subject: [FFmpeg-devel] [PATCH v2] x11grab: capture a window instead of the whole screen X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: X2OgNDU1a9UP On Sat, 6 Feb 2021, Paul B Mahol wrote: > What happens if you use non-existing window? I added an error message for this case, but the output video is still created (empty). Is there a value I can return to avoid this? On Sun, 7 Feb 2021, Andriy Gelman wrote: > Also the commit title should start with avdevice/xcbgrab: or lavd/xcbgrab: > done > > If you try with -show_region 1, the border gets drawn in the wrong place. > fixed I also fixed the misalignement of draw_mouse I didn't notice last time. >> >> +@item window_id >> +Grab this window, instead of the whole screen. >> + > > I think it would be useful to say how to get a window id. > Probably worth adding what happens if the window size changes or it > disappears. > Done. Recording also ends when the window is iconified or reduced in size beyond the video size. For now I disabled follow_mouse and select_region when window_id is given. > xcb_window_t is uint32_t, so max should be UINT32_MAX? Indeed. >> @@ -825,6 +827,9 @@ static av_cold int xcbgrab_read_header(AVFormatContext >> *s) >> return AVERROR(EIO); >> } >> >> + if (c->window_id == 0) >> + c->window_id = c->screen->root; >> + > > Can 0 be a valid window_id? Maybe it's better to use -1 for default. I saw the > function xcb_generate_id() returns -1 on error. > 0 is not a valid x11 identifier, but it's better to use the XCB_NONE macro for it (in Xlib and higher-level libraries, it's "None") Thanks! > Thanks, > -- > Andriy > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". From e13c1be7abd6989b3ad80fd8086fe6a0819fd810 Mon Sep 17 00:00:00 2001 From: sgerwk Date: Wed, 10 Feb 2021 17:36:00 +0100 Subject: [PATCH] libavdevice/xcbgrab: option for grabbing a window instead of desktop --- doc/indevs.texi | 14 +++++++- libavdevice/xcbgrab.c | 79 ++++++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 3924d03..48fd2b1 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -1564,8 +1564,20 @@ With @var{follow_mouse}: ffmpeg -f x11grab -follow_mouse centered -show_region 1 -framerate 25 -video_size cif -i :0.0 out.mpg @end example +@item window_id +Grab this window, instead of the whole screen. + +The id of a window can be found by xwininfo(1), possibly with options -tree and +-root. + +If the window is later enlarged, the new area is not recorded. Video ends when +the window is closed, unmapped (i.e., iconified) or shrunk beyond the video +size (which defaults to the initial window size). + +This option disables options @option{follow_mouse} and @option{select_region}. + @item video_size -Set the video frame size. Default is the full desktop. +Set the video frame size. Default is the full desktop or window. @item grab_x @item grab_y diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c index be5d5ea..7697090 100644 --- a/libavdevice/xcbgrab.c +++ b/libavdevice/xcbgrab.c @@ -60,6 +60,8 @@ typedef struct XCBGrabContext { AVRational time_base; int64_t frame_duration; + xcb_window_t window_id; + int win_x, win_y; int x, y; int width, height; int frame_size; @@ -82,6 +84,7 @@ typedef struct XCBGrabContext { #define OFFSET(x) offsetof(XCBGrabContext, x) #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { + { "window_id", "Window to capture", OFFSET(window_id), AV_OPT_TYPE_INT, { .i64 = XCB_NONE }, 0, UINT32_MAX, D }, { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, @@ -157,7 +160,7 @@ static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt) XCBGrabContext *c = s->priv_data; xcb_get_image_cookie_t iq; xcb_get_image_reply_t *img; - xcb_drawable_t drawable = c->screen->root; + xcb_drawable_t drawable = c->window_id; xcb_generic_error_t *e = NULL; uint8_t *data; int length; @@ -267,7 +270,7 @@ static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) XCBGrabContext *c = s->priv_data; xcb_shm_get_image_cookie_t iq; xcb_shm_get_image_reply_t *img; - xcb_drawable_t drawable = c->screen->root; + xcb_drawable_t drawable = c->window_id; xcb_generic_error_t *e = NULL; AVBufferRef *buf; xcb_shm_seg_t segment; @@ -355,17 +358,17 @@ static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt, cx = ci->x - ci->xhot; cy = ci->y - ci->yhot; - x = FFMAX(cx, gr->x); - y = FFMAX(cy, gr->y); + x = FFMAX(cx, gr->win_x + gr->x); + y = FFMAX(cy, gr->win_y + gr->y); - w = FFMIN(cx + ci->width, gr->x + gr->width) - x; - h = FFMIN(cy + ci->height, gr->y + gr->height) - y; + w = FFMIN(cx + ci->width, gr->win_x + gr->x + gr->width) - x; + h = FFMIN(cy + ci->height, gr->win_y + gr->y + gr->height) - y; c_off = x - cx; - i_off = x - gr->x; + i_off = x - gr->x - gr->win_x; cursor += (y - cy) * ci->width; - image += (y - gr->y) * gr->width * stride; + image += (y - gr->y - gr->win_y) * gr->width * stride; for (y = 0; y < h; y++) { cursor += c_off; @@ -403,8 +406,8 @@ static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt, static void xcbgrab_update_region(AVFormatContext *s) { XCBGrabContext *c = s->priv_data; - const uint32_t args[] = { c->x - c->region_border, - c->y - c->region_border }; + const uint32_t args[] = { c->win_x + c->x - c->region_border, + c->win_y + c->y - c->region_border }; xcb_configure_window(c->conn, c->window, @@ -417,16 +420,22 @@ static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt) XCBGrabContext *c = s->priv_data; xcb_query_pointer_cookie_t pc; xcb_get_geometry_cookie_t gc; + xcb_translate_coordinates_cookie_t tc; xcb_query_pointer_reply_t *p = NULL; xcb_get_geometry_reply_t *geo = NULL; + xcb_translate_coordinates_reply_t *translate = NULL; int ret = 0; int64_t pts; pts = wait_frame(s, pkt); - if (c->follow_mouse || c->draw_mouse) { - pc = xcb_query_pointer(c->conn, c->screen->root); - gc = xcb_get_geometry(c->conn, c->screen->root); + if (c->window_id == c->screen->root) { + c->win_x = 0; + c->win_y = 0; + } + if (c->follow_mouse || c->draw_mouse || c->window_id != c->screen->root) { + pc = xcb_query_pointer(c->conn, c->window_id); + gc = xcb_get_geometry(c->conn, c->window_id); p = xcb_query_pointer_reply(c->conn, pc, NULL); if (!p) { av_log(s, AV_LOG_ERROR, "Failed to query xcb pointer\n"); @@ -438,6 +447,12 @@ static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt) free(p); return AVERROR_EXTERNAL; } + tc = xcb_translate_coordinates(c->conn, c->window_id, c->screen->root, geo->x, geo->y); + translate = xcb_translate_coordinates_reply(c->conn, tc, NULL); + if (!translate) + return AVERROR_EXTERNAL; + c->win_x = translate->dst_x; + c->win_y = translate->dst_y; } if (c->follow_mouse && p->same_screen) @@ -447,7 +462,7 @@ static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt) xcbgrab_update_region(s); #if CONFIG_LIBXCB_SHM - if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) { + if (c->has_shm && (ret = xcbgrab_frame_shm(s, pkt)) == AVERROR(ENOMEM)) { av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n"); c->has_shm = 0; } @@ -558,7 +573,9 @@ static int create_stream(AVFormatContext *s) XCBGrabContext *c = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); xcb_get_geometry_cookie_t gc; + xcb_translate_coordinates_cookie_t tc; xcb_get_geometry_reply_t *geo; + xcb_translate_coordinates_reply_t *translate; int64_t frame_size_bits; int ret; @@ -571,11 +588,20 @@ static int create_stream(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 1000000); - gc = xcb_get_geometry(c->conn, c->screen->root); + gc = xcb_get_geometry(c->conn, c->window_id); geo = xcb_get_geometry_reply(c->conn, gc, NULL); - if (!geo) + if (!geo) { + av_log(s, AV_LOG_ERROR, "Can't find window '0x%x', aborting.\n", c->window_id); + return AVERROR_EXTERNAL; + } + + tc = xcb_translate_coordinates(c->conn, c->window_id, c->screen->root, geo->x, geo->y); + translate = xcb_translate_coordinates_reply(c->conn, tc, NULL); + if (!translate) return AVERROR_EXTERNAL; + c->win_x = translate->dst_x; + c->win_y = translate->dst_y; if (!c->width || !c->height) { c->width = geo->width; c->height = geo->height; @@ -750,7 +776,7 @@ static int select_region(AVFormatContext *s) press_position = (xcb_point_t){ press->event_x, press->event_y }; rectangle.x = press_position.x; rectangle.y = press_position.y; - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); was_pressed = 1; break; } @@ -759,14 +785,14 @@ static int select_region(AVFormatContext *s) xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event; xcb_point_t cursor_position = { motion->event_x, motion->event_y }; - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); rectangle = rectangle_from_corners(&press_position, &cursor_position); - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); } break; } case XCB_BUTTON_RELEASE: { - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); done = 1; break; } @@ -830,6 +856,19 @@ static av_cold int xcbgrab_read_header(AVFormatContext *s) return AVERROR(EIO); } + if (c->window_id == XCB_NONE) + c->window_id = c->screen->root; + else { + if (c->select_region) { + av_log(s, AV_LOG_WARNING, "select_region ignored with window_id.\n"); + c->select_region = 0; + } + if (c->follow_mouse) { + av_log(s, AV_LOG_WARNING, "follow_mouse ignored with window_id.\n"); + c->follow_mouse = 0; + } + } + if (c->select_region) { ret = select_region(s); if (ret < 0) {