summaryrefslogtreecommitdiffstats
path: root/src/plugins/multimedia/ffmpeg/qwincapturablewindows.cpp
blob: aac77aec4dc58cdbfcf9d56cde0e15636047c9ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "qwincapturablewindows_p.h"
#include "private/qcapturablewindow_p.h"

#include <qt_windows.h>

QT_BEGIN_NAMESPACE

static bool isTopLevelWindow(HWND hwnd)
{
    return hwnd && ::GetAncestor(hwnd, GA_ROOT) == hwnd;
}

static bool canCaptureWindow(HWND hwnd)
{
    Q_ASSERT(hwnd);

    if (!::IsWindowVisible(hwnd))
        return false;

    RECT rect{};
    if (!::GetWindowRect(hwnd, &rect))
        return false;

    if (rect.left >= rect.right || rect.top >= rect.bottom)
        return false;

    return true;
}

static QString windowTitle(HWND hwnd) {
    // QTBUG-114890
    // TODO: investigate the case when hwnd is inner and belows to another thread.
    // It might causes deadlocks in specific cases.
    auto titleLength = ::GetWindowTextLengthW(hwnd);
    std::wstring buffer(titleLength + 1, L'\0');
    titleLength = ::GetWindowTextW(hwnd, buffer.data(), titleLength + 1);
    buffer.resize(titleLength);

    return QString::fromStdWString(buffer);
}

QList<QCapturableWindow> QWinCapturableWindows::windows() const
{
    QList<QCapturableWindow> result;

    auto windowHandler = [](HWND hwnd, LPARAM lParam) {
        if (!canCaptureWindow(hwnd))
            return TRUE; // Ignore window and continue enumerating

        auto& windows = *reinterpret_cast<QList<QCapturableWindow>*>(lParam);

        auto windowData = std::make_unique<QCapturableWindowPrivate>();
        windowData->id = reinterpret_cast<QCapturableWindowPrivate::Id>(hwnd);
        windowData->description = windowTitle(hwnd);
        windows.push_back(windowData.release()->create());

        return TRUE;
    };

    ::EnumWindows(windowHandler, reinterpret_cast<LPARAM>(&result));

    return result;
}

bool QWinCapturableWindows::isWindowValid(const QCapturableWindowPrivate &window) const
{
    const auto hwnd = reinterpret_cast<HWND>(window.id);
    return isTopLevelWindow(hwnd) && canCaptureWindow(hwnd);
}

QT_END_NAMESPACE