Skip to content

Commit 7d37168

Browse files
committed
feat: capture windows and monitors on Windows with Windows Graphics Capture
1 parent 809b925 commit 7d37168

6 files changed

Lines changed: 622 additions & 5 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ elseif(WIN32)
9494
src/platform/windows/WinMouseBackend.cpp
9595
src/platform/windows/WinScreenBackend.cpp
9696
src/platform/windows/WinEventTapBackend.cpp
97+
src/platform/windows/WinWindowBackend.cpp
9798
)
9899
elseif(UNIX AND NOT APPLE)
99100
set(ROBOT_PLATFORM_SOURCES
@@ -166,7 +167,8 @@ elseif(WIN32)
166167
# user32/gdi32 for SendInput, hooks, GDI capture. Shcore and the DPI context
167168
# API are resolved at runtime (see WinDpi.cpp / WinScreenBackend.cpp), so they
168169
# are not linked here.
169-
target_link_libraries(robot PRIVATE user32 gdi32)
170+
# d3d11, dxgi, dwmapi and windowsapp for Windows Graphics Capture.
171+
target_link_libraries(robot PRIVATE user32 gdi32 d3d11 dxgi dwmapi shcore windowsapp)
170172
target_compile_definitions(robot PRIVATE
171173
WIN32_LEAN_AND_MEAN NOMINMAX UNICODE _UNICODE)
172174
elseif(UNIX AND NOT APPLE)

‎include/robot/win/VideoFrame.h‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
// Typed Windows bridge for VideoFrame's platform buffer. Include this from
4+
// Windows-only translation units instead of casting nativeHandle() by hand.
5+
6+
#include <cstdint>
7+
8+
#include "robot/VideoFrame.h"
9+
10+
namespace robot::win {
11+
12+
// Frame pixels mapped for CPU reads, BGRA and top-down. Valid for the frame's
13+
// lifetime, and safe to read from any thread.
14+
struct PixelBuffer {
15+
const std::uint8_t* pixels = nullptr;
16+
int width = 0;
17+
int height = 0;
18+
int bytesPerRow = 0;
19+
};
20+
21+
[[nodiscard]] inline const PixelBuffer& pixelBuffer(const VideoFrame& frame) {
22+
return *static_cast<const PixelBuffer*>(frame.nativeHandle());
23+
}
24+
25+
} // namespace robot::win

‎src/platform/windows/WinBackendFactory.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Capabilities buildCapabilities() {
2424
c.canCaptureScreen = true;
2525
c.canEnumerateMonitors = true;
2626
c.canRecordEvents = true;
27+
c.canEnumerateWindows = true;
28+
c.canStreamWindows = true;
2729

2830
c.requiresAccessibilityPermission = false;
2931
c.requiresScreenRecordingPermission = false;

‎src/platform/windows/WinPlatformBackend.h‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
#include "WinKeyboardBackend.h"
77
#include "WinMouseBackend.h"
88
#include "WinScreenBackend.h"
9+
#include "WinWindowBackend.h"
910
#include "robot/backend/IPlatformBackend.h"
1011

1112
namespace robot::win {
1213

13-
// Owns the four Windows sub-backends and the capabilities report. A Session owns
14+
// Owns the five Windows sub-backends and the capabilities report. A Session owns
1415
// exactly one of these.
1516
class WinPlatformBackend final : public backend::IPlatformBackend {
1617
public:
@@ -19,14 +20,14 @@ class WinPlatformBackend final : public backend::IPlatformBackend {
1920
keyboard_(std::make_unique<WinKeyboardBackend>()),
2021
mouse_(std::make_unique<WinMouseBackend>()),
2122
screen_(std::make_unique<WinScreenBackend>()),
22-
eventTap_(std::make_unique<WinEventTapBackend>()) {}
23+
eventTap_(std::make_unique<WinEventTapBackend>()),
24+
windows_(std::make_unique<WinWindowBackend>()) {}
2325

2426
backend::IKeyboardBackend& keyboard() override { return *keyboard_; }
2527
backend::IMouseBackend& mouse() override { return *mouse_; }
2628
backend::IScreenBackend& screen() override { return *screen_; }
2729
backend::IEventTapBackend* eventTap() override { return eventTap_.get(); }
28-
// Window enumeration/capture is not implemented on this platform yet.
29-
backend::IWindowBackend* windows() override { return nullptr; }
30+
backend::IWindowBackend* windows() override { return windows_.get(); }
3031
const Capabilities& capabilities() const override { return capabilities_; }
3132

3233
private:
@@ -35,6 +36,7 @@ class WinPlatformBackend final : public backend::IPlatformBackend {
3536
std::unique_ptr<WinMouseBackend> mouse_;
3637
std::unique_ptr<WinScreenBackend> screen_;
3738
std::unique_ptr<WinEventTapBackend> eventTap_;
39+
std::unique_ptr<WinWindowBackend> windows_;
3840
};
3941

4042
} // namespace robot::win

0 commit comments

Comments
 (0)