mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-27 04:35:34 +08:00
[feat] add display selection method for Windows platform
This commit is contained in:
@@ -11,7 +11,18 @@
|
|||||||
|
|
||||||
class ScreenCapturer {
|
class ScreenCapturer {
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(unsigned char *, int, int, int)> cb_desktop_data;
|
typedef std::function<void(unsigned char*, int, int, int)> cb_desktop_data;
|
||||||
|
|
||||||
|
class DisplayInfo {
|
||||||
|
public:
|
||||||
|
void* handle = nullptr;
|
||||||
|
std::string name = "";
|
||||||
|
bool is_primary = false;
|
||||||
|
int left = 0;
|
||||||
|
int top = 0;
|
||||||
|
int right = 0;
|
||||||
|
int bottom = 0;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~ScreenCapturer() {}
|
virtual ~ScreenCapturer() {}
|
||||||
@@ -21,6 +32,8 @@ class ScreenCapturer {
|
|||||||
virtual int Destroy() = 0;
|
virtual int Destroy() = 0;
|
||||||
virtual int Start() = 0;
|
virtual int Start() = 0;
|
||||||
virtual int Stop() = 0;
|
virtual int Stop() = 0;
|
||||||
|
|
||||||
|
virtual std::vector<DisplayInfo> GetDisplayList() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -8,17 +8,36 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "libyuv.h"
|
#include "libyuv.h"
|
||||||
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
static std::vector<ScreenCapturer::DisplayInfo> gs_display_list;
|
||||||
|
|
||||||
|
std::string WideToUtf8(const wchar_t *wideStr) {
|
||||||
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0,
|
||||||
|
nullptr, nullptr);
|
||||||
|
std::string result(size_needed, 0);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, &result[0], size_needed, nullptr,
|
||||||
|
nullptr);
|
||||||
|
result.pop_back();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
|
BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
|
||||||
[[maybe_unused]] LPRECT lprc, LPARAM data) {
|
[[maybe_unused]] LPRECT lprc, LPARAM data) {
|
||||||
MONITORINFOEX info_ex;
|
MONITORINFOEX monitor_info_;
|
||||||
info_ex.cbSize = sizeof(MONITORINFOEX);
|
monitor_info_.cbSize = sizeof(MONITORINFOEX);
|
||||||
|
|
||||||
GetMonitorInfo(hmonitor, &info_ex);
|
if (GetMonitorInfo(hmonitor, &monitor_info_)) {
|
||||||
|
gs_display_list.push_back(
|
||||||
|
{(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
||||||
|
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
||||||
|
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
||||||
|
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom});
|
||||||
|
}
|
||||||
|
|
||||||
if (info_ex.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true;
|
if (monitor_info_.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true;
|
||||||
|
|
||||||
if (info_ex.dwFlags & MONITORINFOF_PRIMARY) {
|
if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) {
|
||||||
*(HMONITOR *)data = hmonitor;
|
*(HMONITOR *)data = hmonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,12 +47,13 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
|
|||||||
HMONITOR GetPrimaryMonitor() {
|
HMONITOR GetPrimaryMonitor() {
|
||||||
HMONITOR hmonitor = nullptr;
|
HMONITOR hmonitor = nullptr;
|
||||||
|
|
||||||
|
gs_display_list.clear();
|
||||||
::EnumDisplayMonitors(NULL, NULL, EnumMonitorProc, (LPARAM)&hmonitor);
|
::EnumDisplayMonitors(NULL, NULL, EnumMonitorProc, (LPARAM)&hmonitor);
|
||||||
|
|
||||||
return hmonitor;
|
return hmonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenCapturerWgc::ScreenCapturerWgc() {}
|
ScreenCapturerWgc::ScreenCapturerWgc() : monitor_(nullptr) {}
|
||||||
|
|
||||||
ScreenCapturerWgc::~ScreenCapturerWgc() {
|
ScreenCapturerWgc::~ScreenCapturerWgc() {
|
||||||
Stop();
|
Stop();
|
||||||
@@ -89,7 +109,17 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) {
|
|||||||
|
|
||||||
session_->RegisterObserver(this);
|
session_->RegisterObserver(this);
|
||||||
|
|
||||||
error = session_->Initialize(GetPrimaryMonitor());
|
monitor_ = GetPrimaryMonitor();
|
||||||
|
|
||||||
|
display_list_ = gs_display_list;
|
||||||
|
|
||||||
|
for (const auto &display : display_list_) {
|
||||||
|
LOG_INFO("Display Name: {}, Is Primary: {}, Bounds: ({}, {}) - ({}, {})",
|
||||||
|
display.name, (display.is_primary ? "Yes" : "No"), display.left,
|
||||||
|
display.top, display.right, display.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = session_->Initialize(monitor_);
|
||||||
|
|
||||||
_inited = true;
|
_inited = true;
|
||||||
} while (0);
|
} while (0);
|
||||||
@@ -139,6 +169,44 @@ int ScreenCapturerWgc::Stop() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScreenCapturerWgc::SwitchTo(int monitor_index) {
|
||||||
|
if (!_inited) return -1;
|
||||||
|
if (monitor_index >= display_list_.size()) {
|
||||||
|
LOG_ERROR("Invalid monitor index: {}", monitor_index);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Switching to monitor {}:{}", monitor_index,
|
||||||
|
display_list_[monitor_index].name);
|
||||||
|
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
if (session_) {
|
||||||
|
session_->Release();
|
||||||
|
delete session_;
|
||||||
|
session_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_ = new WgcSessionImpl();
|
||||||
|
if (!session_) {
|
||||||
|
LOG_ERROR("Failed to create new WgcSessionImpl.");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_->RegisterObserver(this);
|
||||||
|
|
||||||
|
int err = session_->Initialize((HMONITOR)display_list_[monitor_index].handle);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_ERROR("Failed to re-initialize session on new monitor.");
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_ = (HMONITOR)display_list_[monitor_index].handle;
|
||||||
|
_inited = true;
|
||||||
|
|
||||||
|
return Start();
|
||||||
|
}
|
||||||
|
|
||||||
void ConvertABGRtoBGRA(const uint8_t *abgr_data, uint8_t *bgra_data, int width,
|
void ConvertABGRtoBGRA(const uint8_t *abgr_data, uint8_t *bgra_data, int width,
|
||||||
int height, int abgr_stride, int bgra_stride) {
|
int height, int abgr_stride, int bgra_stride) {
|
||||||
for (int i = 0; i < height; ++i) {
|
for (int i = 0; i < height; ++i) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "screen_capturer.h"
|
#include "screen_capturer.h"
|
||||||
#include "wgc_session.h"
|
#include "wgc_session.h"
|
||||||
@@ -27,11 +28,20 @@ class ScreenCapturerWgc : public ScreenCapturer,
|
|||||||
int Pause();
|
int Pause();
|
||||||
int Resume();
|
int Resume();
|
||||||
|
|
||||||
|
std::vector<DisplayInfo> GetDisplayList() { return display_list_; }
|
||||||
|
|
||||||
|
int SwitchTo(int monitor_index);
|
||||||
|
|
||||||
void OnFrame(const WgcSession::wgc_session_frame &frame);
|
void OnFrame(const WgcSession::wgc_session_frame &frame);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CleanUp();
|
void CleanUp();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HMONITOR monitor_;
|
||||||
|
MONITORINFOEX monitor_info_;
|
||||||
|
std::vector<DisplayInfo> display_list_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WgcSession *session_ = nullptr;
|
WgcSession *session_ = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class WgcSession {
|
|||||||
virtual int Pause() = 0;
|
virtual int Pause() = 0;
|
||||||
virtual int Resume() = 0;
|
virtual int Resume() = 0;
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~WgcSession(){};
|
virtual ~WgcSession(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,28 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
2.0f);
|
2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const char* items[] = {"1", "2", "3"};
|
||||||
|
// static int item_selected_idx = 0;
|
||||||
|
// ImGui::Text("Display:");
|
||||||
|
// ImGui::SameLine();
|
||||||
|
// ImGui::SetNextItemWidth(25.0f);
|
||||||
|
// ImGuiComboFlags flags =
|
||||||
|
// ImGuiComboFlags_HeightSmall | ImGuiComboFlags_NoArrowButton;
|
||||||
|
// const char* combo_preview_value = items[item_selected_idx];
|
||||||
|
// ImGui::SetWindowFontScale(1.2f);
|
||||||
|
// if (ImGui::BeginCombo("##display", combo_preview_value, flags)) {
|
||||||
|
// ImGui::SetWindowFontScale(0.5f);
|
||||||
|
// for (int n = 0; n < IM_ARRAYSIZE(items); n++) {
|
||||||
|
// const bool is_selected = (item_selected_idx == n);
|
||||||
|
// if (ImGui::Selectable(items[n], is_selected)) item_selected_idx = n;
|
||||||
|
|
||||||
|
// if (is_selected) ImGui::SetItemDefaultFocus();
|
||||||
|
// }
|
||||||
|
// ImGui::SetWindowFontScale(1.0f);
|
||||||
|
// ImGui::EndCombo();
|
||||||
|
// }
|
||||||
|
// ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
// audio capture button
|
// audio capture button
|
||||||
float disable_audio_x = ImGui::GetCursorScreenPos().x + 4;
|
float disable_audio_x = ImGui::GetCursorScreenPos().x + 4;
|
||||||
|
|||||||
Reference in New Issue
Block a user