diff mbox series

[FFmpeg-devel] avdevice/gdigrab: client_only option to discard decorations such as titlebar or borders

Message ID 59E47B81-05C3-4C9E-A7DE-7A498A5B871D@gmail.com
State New
Headers show
Series [FFmpeg-devel] avdevice/gdigrab: client_only option to discard decorations such as titlebar or borders
Related show

Checks

Context Check Description
andriy/default pending
andriy/configure warning Failed to apply patch

Commit Message

Sergio Acereda June 19, 2020, 8:33 a.m. UTC
---
libavdevice/gdigrab.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Comments

Moritz Barsnick June 24, 2020, 9:29 a.m. UTC | #1
On Fri, Jun 19, 2020 at 10:33:00 +0200, Sergio Acereda wrote:

> +static int
> +calc_titlebar_height(HWND hwnd) {

Nit: the opening bracket of a function belongs in the next line.

>         GetClientRect(hwnd, &virtual_rect);
> +        if (gdigrab->client_only) {
> +            int cxborder = GetSystemMetrics(SM_CXBORDER);
> +            int cyborder = GetSystemMetrics(SM_CYBORDER);
> +            int titlebar_height = calc_titlebar_height(hwnd);
> +            virtual_rect.left   += cxborder;
> +            virtual_rect.right  += -cxborder;
> +            virtual_rect.top    += cxborder + titlebar_height;
> +            virtual_rect.bottom += -cyborder;
> +        }

Does this actually work correctly? Just wondering, as I read this:
https://stackoverflow.com/a/11707312/3974309
I can't test, sorry.

> +    { "client_only", "client only", OFFSET(client_only), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },

Please also update the documentation (doc/indevs.texi).

Thanks,
Moritz
Calvin Walton July 9, 2020, 4:52 p.m. UTC | #2
On Fri, 2020-06-19 at 10:33 +0200, Sergio Acereda wrote:
> +/**
> + * Fetch titlebar height from handle.
> + *
> + * @param hwnd Handle of the window.
> + * @return titlebar height
> + */
> +static int
> +calc_titlebar_height(HWND hwnd) {
> +    TITLEBARINFOEX tinfo;
> +    tinfo.cbSize = sizeof(tinfo);
> +    SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0, (LPARAM)&tinfo);
> +    return tinfo.rcTitleBar.bottom - tinfo.rcTitleBar.top;
> +}
> +
> /**
>  * Initializes the gdi grab device demuxer (public device demuxer
> API).
>  *
> @@ -284,6 +299,15 @@ gdigrab_read_header(AVFormatContext *s1)
> 
>     if (hwnd) {
>         GetClientRect(hwnd, &virtual_rect);
> +        if (gdigrab->client_only) {
> +            int cxborder = GetSystemMetrics(SM_CXBORDER);
> +            int cyborder = GetSystemMetrics(SM_CYBORDER);
> +            int titlebar_height = calc_titlebar_height(hwnd);
> +            virtual_rect.left   += cxborder;
> +            virtual_rect.right  += -cxborder;
> +            virtual_rect.top    += cxborder + titlebar_height;
> +            virtual_rect.bottom += -cyborder;
> +        }

This seems fine - my only comment is that you need to test this with
high DPI support (display scale values >100%) on both native high-dpi
applications and legacy (scaled by windows) applications to ensure the
correct adjustments are being applied where needed.
diff mbox series

Patch

diff --git a/libavdevice/gdigrab.c b/libavdevice/gdigrab.c
index f4444406fa..b09c88d94d 100644
--- a/libavdevice/gdigrab.c
+++ b/libavdevice/gdigrab.c
@@ -52,6 +52,7 @@  struct gdigrab {
    int        height;      /**< Height of the grab frame (private option) */
    int        offset_x;    /**< Capture x offset (private option) */
    int        offset_y;    /**< Capture y offset (private option) */
+    int        client_only; /**< Discard decorations, such as titlebar (private option) */

    HWND       hwnd;        /**< Handle of the window for the grab */
    HDC        source_hdc;  /**< Source device context */
@@ -212,6 +213,20 @@  gdigrab_region_wnd_update(AVFormatContext *s1, struct gdigrab *gdigrab)
    }
}

+/**
+ * Fetch titlebar height from handle.
+ *
+ * @param hwnd Handle of the window.
+ * @return titlebar height
+ */
+static int
+calc_titlebar_height(HWND hwnd) {
+    TITLEBARINFOEX tinfo;
+    tinfo.cbSize = sizeof(tinfo);
+    SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0, (LPARAM)&tinfo);
+    return tinfo.rcTitleBar.bottom - tinfo.rcTitleBar.top;
+}
+
/**
 * Initializes the gdi grab device demuxer (public device demuxer API).
 *
@@ -284,6 +299,15 @@  gdigrab_read_header(AVFormatContext *s1)

    if (hwnd) {
        GetClientRect(hwnd, &virtual_rect);
+        if (gdigrab->client_only) {
+            int cxborder = GetSystemMetrics(SM_CXBORDER);
+            int cyborder = GetSystemMetrics(SM_CYBORDER);
+            int titlebar_height = calc_titlebar_height(hwnd);
+            virtual_rect.left   += cxborder;
+            virtual_rect.right  += -cxborder;
+            virtual_rect.top    += cxborder + titlebar_height;
+            virtual_rect.bottom += -cyborder;
+        }
        /* window -- get the right height and width for scaling DPI */
        virtual_rect.left   = virtual_rect.left   * desktophorzres / horzres;
        virtual_rect.right  = virtual_rect.right  * desktophorzres / horzres;
@@ -639,6 +663,7 @@  static const AVOption options[] = {
    { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
    { "offset_x", "capture area x offset", OFFSET(offset_x), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
    { "offset_y", "capture area y offset", OFFSET(offset_y), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
+    { "client_only", "client only", OFFSET(client_only), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
    { NULL },
};