4 Commits

Author SHA1 Message Date
dijunkun
2c622bc76e [ci] update GitHub Actions to use macos-13 runner instead of macos-15 for Intel builds 2025-10-27 22:31:23 +08:00
dijunkun
b790c7d08e [chore] update README 2025-10-27 22:11:30 +08:00
dijunkun
0ca90d2516 [chore] move minirtc into submodules 2025-10-27 21:36:11 +08:00
dijunkun
401bfe4483 [refactor] add namespace 'crossdesk' to codebase 2025-10-27 21:09:39 +08:00
75 changed files with 319 additions and 612 deletions

View File

@@ -144,7 +144,7 @@ jobs:
matrix:
include:
- arch: x64
runner: macos-15-intel
runner: macos-13
cache-key: intel
out-dir: ./build/macosx/x86_64/release/crossdesk
package_script: ./scripts/macosx/pkg_x64.sh

4
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "thirdparty/minirtc"]
path = thirdparty/minirtc
[submodule "submodules/minirtc"]
path = submodules/minirtc
url = https://github.com/kunkundi/minirtc.git

View File

@@ -1,6 +1,6 @@
# CrossDesk
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)]()
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-brightgreen.svg)]()
[![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
[![GitHub last commit](https://img.shields.io/github/last-commit/kunkundi/crossdesk)](https://github.com/kunkundi/crossdesk/commits/self-hosted-server)
[![Build Status](https://github.com/kunkundi/crossdesk/actions/workflows/build.yml/badge.svg)](https://github.com/kunkundi/crossdesk/actions)

View File

@@ -1,6 +1,6 @@
# CrossDesk
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)]()
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-brightgreen.svg)]()
[![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
[![GitHub last commit](https://img.shields.io/github/last-commit/kunkundi/crossdesk)](https://github.com/kunkundi/crossdesk/commits/self-hosted-server)
[![Build Status](https://github.com/kunkundi/crossdesk/actions/workflows/build.yml/badge.svg)](https://github.com/kunkundi/crossdesk/actions)

View File

@@ -9,8 +9,8 @@
#include "rd_log.h"
#include "render.h"
int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) {
Render render;
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
crossdesk::Render render;
render.Run();
return 0;

View File

@@ -9,6 +9,8 @@
#include <string>
namespace crossdesk {
class DisplayInfo {
public:
DisplayInfo(std::string name, int left, int top, int right, int bottom)
@@ -40,5 +42,5 @@ class DisplayInfo {
int width = 0;
int height = 0;
};
} // namespace crossdesk
#endif

View File

@@ -19,6 +19,8 @@
#include <unistd.h>
#endif
namespace crossdesk {
std::string GetMac() {
char mac_addr[16];
int len = 0;
@@ -39,21 +41,21 @@ std::string GetMac() {
#elif __APPLE__
std::string if_name = "en0";
struct ifaddrs *addrs;
struct ifaddrs *cursor;
const struct sockaddr_dl *dlAddr;
struct ifaddrs* addrs;
struct ifaddrs* cursor;
const struct sockaddr_dl* dlAddr;
if (!getifaddrs(&addrs)) {
cursor = addrs;
while (cursor != 0) {
const struct sockaddr_dl *socAddr =
(const struct sockaddr_dl *)cursor->ifa_addr;
const struct sockaddr_dl* socAddr =
(const struct sockaddr_dl*)cursor->ifa_addr;
if ((cursor->ifa_addr->sa_family == AF_LINK) &&
(socAddr->sdl_type == IFT_ETHER) &&
strcmp(if_name.c_str(), cursor->ifa_name) == 0) {
dlAddr = (const struct sockaddr_dl *)cursor->ifa_addr;
const unsigned char *base =
(const unsigned char *)&dlAddr->sdl_data[dlAddr->sdl_nlen];
dlAddr = (const struct sockaddr_dl*)cursor->ifa_addr;
const unsigned char* base =
(const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen];
for (int i = 0; i < dlAddr->sdl_alen; i++) {
len +=
snprintf(mac_addr + len, sizeof(mac_addr) - len, "%.2X", base[i]);
@@ -77,8 +79,8 @@ std::string GetMac() {
close(sock);
return "";
}
struct ifreq *it = ifc.ifc_req;
const struct ifreq *const end = it + (ifc.ifc_len / sizeof(struct ifreq));
struct ifreq* it = ifc.ifc_req;
const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
for (; it != end; ++it) {
std::strcpy(ifr.ifr_name, it->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
@@ -123,3 +125,4 @@ std::string GetHostName() {
#endif
return hostname;
}
} // namespace crossdesk

View File

@@ -9,7 +9,10 @@
#include <iostream>
namespace crossdesk {
std::string GetMac();
std::string GetHostName();
} // namespace crossdesk
#endif

View File

@@ -1,5 +1,7 @@
#include "config_center.h"
namespace crossdesk {
ConfigCenter::ConfigCenter(const std::string& config_path,
const std::string& cert_file_path)
: config_path_(config_path),
@@ -264,3 +266,4 @@ std::string ConfigCenter::GetDefaultCertFilePath() const {
bool ConfigCenter::IsSelfHosted() const { return enable_self_hosted_; }
bool ConfigCenter::IsMinimizeToTray() const { return enable_minimize_to_tray_; }
} // namespace crossdesk

View File

@@ -11,6 +11,8 @@
#include "SimpleIni.h"
namespace crossdesk {
class ConfigCenter {
public:
enum class LANGUAGE { CHINESE = 0, ENGLISH = 1 };
@@ -85,5 +87,5 @@ class ConfigCenter {
bool enable_self_hosted_ = false;
bool enable_minimize_to_tray_ = false;
};
} // namespace crossdesk
#endif

View File

@@ -11,6 +11,8 @@
#include "display_info.h"
namespace crossdesk {
typedef enum {
mouse = 0,
keyboard,
@@ -79,5 +81,5 @@ class DeviceController {
// virtual int Hook();
// virtual int Unhook();
};
} // namespace crossdesk
#endif

View File

@@ -11,6 +11,8 @@
#include "keyboard_capturer.h"
#include "mouse_controller.h"
namespace crossdesk {
class DeviceControllerFactory {
public:
enum Device { Mouse = 0, Keyboard };
@@ -30,5 +32,5 @@ class DeviceControllerFactory {
}
}
};
} // namespace crossdesk
#endif

View File

@@ -3,6 +3,8 @@
#include "keyboard_converter.h"
#include "rd_log.h"
namespace crossdesk {
static OnKeyAction g_on_key_action = nullptr;
static void* g_user_ptr = nullptr;
@@ -67,3 +69,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
}
return 0;
}
} // namespace crossdesk

View File

@@ -13,20 +13,22 @@
#include "device_controller.h"
namespace crossdesk {
class KeyboardCapturer : public DeviceController {
public:
KeyboardCapturer();
virtual ~KeyboardCapturer();
public:
virtual int Hook(OnKeyAction on_key_action, void *user_ptr);
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
virtual int Unhook();
virtual int SendKeyboardCommand(int key_code, bool is_down);
private:
Display *display_;
Display* display_;
Window root_;
bool running_;
};
} // namespace crossdesk
#endif

View File

@@ -3,12 +3,14 @@
#include "keyboard_converter.h"
#include "rd_log.h"
namespace crossdesk {
static OnKeyAction g_on_key_action = nullptr;
static void *g_user_ptr = nullptr;
static void* g_user_ptr = nullptr;
CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
CGEventRef event, void *userInfo) {
KeyboardCapturer *keyboard_capturer = (KeyboardCapturer *)userInfo;
CGEventRef event, void* userInfo) {
KeyboardCapturer* keyboard_capturer = (KeyboardCapturer*)userInfo;
if (!keyboard_capturer) {
LOG_ERROR("keyboard_capturer is nullptr");
return event;
@@ -91,7 +93,7 @@ KeyboardCapturer::KeyboardCapturer() {}
KeyboardCapturer::~KeyboardCapturer() {}
int KeyboardCapturer::Hook(OnKeyAction on_key_action, void *user_ptr) {
int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) {
g_on_key_action = on_key_action;
g_user_ptr = user_ptr;
@@ -165,3 +167,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
return 0;
}
} // namespace crossdesk

View File

@@ -11,13 +11,15 @@
#include "device_controller.h"
namespace crossdesk {
class KeyboardCapturer : public DeviceController {
public:
KeyboardCapturer();
virtual ~KeyboardCapturer();
public:
virtual int Hook(OnKeyAction on_key_action, void *user_ptr);
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
virtual int Unhook();
virtual int SendKeyboardCommand(int key_code, bool is_down);
@@ -33,5 +35,5 @@ class KeyboardCapturer : public DeviceController {
bool command_flag_ = false;
int fn_key_code_ = 0x3F;
};
} // namespace crossdesk
#endif

View File

@@ -2,6 +2,8 @@
#include "rd_log.h"
namespace crossdesk {
static OnKeyAction g_on_key_action = nullptr;
static void* g_user_ptr = nullptr;
@@ -54,3 +56,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
return 0;
}
} // namespace crossdesk

View File

@@ -11,18 +11,21 @@
#include "device_controller.h"
namespace crossdesk {
class KeyboardCapturer : public DeviceController {
public:
KeyboardCapturer();
virtual ~KeyboardCapturer();
public:
virtual int Hook(OnKeyAction on_key_action, void *user_ptr);
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
virtual int Unhook();
virtual int SendKeyboardCommand(int key_code, bool is_down);
private:
HHOOK keyboard_hook_ = nullptr;
};
} // namespace crossdesk
#endif

View File

@@ -9,6 +9,8 @@
#include <map>
namespace crossdesk {
// Windows vkCode to macOS CGKeyCode (104 keys)
std::map<int, int> vkCodeToCGKeyCode = {
// A-Z
@@ -736,5 +738,5 @@ std::map<int, int> x11KeySymToCgKeyCode = {
{0xFFEB, 0x37}, // Left Command
{0xFFEC, 0x36}, // Right Command
};
} // namespace crossdesk
#endif

View File

@@ -4,6 +4,8 @@
#include "rd_log.h"
namespace crossdesk {
MouseController::MouseController() {}
MouseController::~MouseController() { Destroy(); }
@@ -122,3 +124,4 @@ void MouseController::SimulateMouseWheel(int direction_button, int count) {
}
XFlush(display_);
}
} // namespace crossdesk

View File

@@ -15,6 +15,8 @@
#include "device_controller.h"
namespace crossdesk {
class MouseController : public DeviceController {
public:
MouseController();
@@ -37,5 +39,5 @@ class MouseController : public DeviceController {
int screen_width_ = 0;
int screen_height_ = 0;
};
} // namespace crossdesk
#endif

View File

@@ -4,6 +4,8 @@
#include "rd_log.h"
namespace crossdesk {
MouseController::MouseController() {}
MouseController::~MouseController() {}
@@ -99,3 +101,4 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
return 0;
}
} // namespace crossdesk

View File

@@ -11,6 +11,8 @@
#include "device_controller.h"
namespace crossdesk {
class MouseController : public DeviceController {
public:
MouseController();
@@ -26,5 +28,5 @@ class MouseController : public DeviceController {
bool left_dragging_ = false;
bool right_dragging_ = false;
};
} // namespace crossdesk
#endif

View File

@@ -2,6 +2,8 @@
#include "rd_log.h"
namespace crossdesk {
MouseController::MouseController() {}
MouseController::~MouseController() {}
@@ -70,3 +72,4 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
return 0;
}
} // namespace crossdesk

View File

@@ -11,6 +11,8 @@
#include "device_controller.h"
namespace crossdesk {
class MouseController : public DeviceController {
public:
MouseController();
@@ -24,5 +26,5 @@ class MouseController : public DeviceController {
private:
std::vector<DisplayInfo> display_info_list_;
};
} // namespace crossdesk
#endif

View File

@@ -12,6 +12,9 @@
#if _WIN32
#include <Windows.h>
#endif
namespace crossdesk {
namespace localization {
static std::vector<std::string> local_desktop = {
@@ -169,4 +172,5 @@ static std::vector<std::string> minimize_to_tray = {
static std::vector<LPCWSTR> exit_program = {L"退出", L"Exit"};
#endif
} // namespace localization
} // namespace crossdesk
#endif

View File

@@ -5,6 +5,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
int Render::LocalWindow() {
ImGui::SetNextWindowPos(ImVec2(-1.0f, title_bar_height_), ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
@@ -288,3 +290,4 @@ int Render::LocalWindow() {
return 0;
}
} // namespace crossdesk

View File

@@ -2,6 +2,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
int Render::RecentConnectionsWindow() {
ImGui::SetNextWindowPos(
ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f),
@@ -284,3 +286,4 @@ int Render::ConfirmDeleteConnection() {
ImGui::PopStyleVar();
return 0;
}
} // namespace crossdesk

View File

@@ -3,7 +3,9 @@
#include "rd_log.h"
#include "render.h"
static int InputTextCallback(ImGuiInputTextCallbackData *data);
namespace crossdesk {
static int InputTextCallback(ImGuiInputTextCallbackData* data);
int Render::RemoteWindow() {
ImGui::SetNextWindowPos(ImVec2(local_window_width_ + 1.0f, title_bar_height_),
@@ -77,7 +79,7 @@ int Render::RemoteWindow() {
enter_pressed) {
connect_button_pressed_ = true;
bool found = false;
for (auto &[id, props] : recent_connections_) {
for (auto& [id, props] : recent_connections_) {
if (id.find(remote_id) != std::string::npos) {
found = true;
if (client_properties_.find(remote_id) !=
@@ -101,7 +103,7 @@ int Render::RemoteWindow() {
if (need_to_rejoin_) {
need_to_rejoin_ = false;
for (const auto &[_, props] : client_properties_) {
for (const auto& [_, props] : client_properties_) {
if (props->rejoin_) {
ConnectTo(props->remote_id_, props->remote_password_,
props->remember_password_);
@@ -117,7 +119,7 @@ int Render::RemoteWindow() {
return 0;
}
static int InputTextCallback(ImGuiInputTextCallbackData *data) {
static int InputTextCallback(ImGuiInputTextCallbackData* data) {
if (data->BufTextLen > 3 && data->Buf[3] != ' ') {
data->InsertChars(3, " ");
}
@@ -129,7 +131,7 @@ static int InputTextCallback(ImGuiInputTextCallbackData *data) {
return 0;
}
int Render::ConnectTo(const std::string &remote_id, const char *password,
int Render::ConnectTo(const std::string& remote_id, const char* password,
bool remember_password) {
LOG_INFO("Connect to [{}]", remote_id);
focused_remote_id_ = remote_id;
@@ -179,3 +181,4 @@ int Render::ConnectTo(const std::string &remote_id, const char *password,
return 0;
}
} // namespace crossdesk

View File

@@ -21,6 +21,8 @@
#define MOUSE_GRAB_PADDING 5
namespace crossdesk {
std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) {
std::vector<char> buffer;
buffer.push_back(static_cast<char>(action.type));
@@ -1432,3 +1434,4 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
break;
}
}
} // namespace crossdesk

View File

@@ -33,6 +33,7 @@
#include "win_tray.h"
#endif
namespace crossdesk {
class Render {
public:
struct SubStreamWindowProperties {
@@ -469,5 +470,5 @@ class Render {
void CloseTab(decltype(client_properties_)::iterator& it);
/* ------ stream window property end ------ */
};
} // namespace crossdesk
#endif

View File

@@ -11,6 +11,8 @@
#define MOUSE_CONTROL 1
#endif
namespace crossdesk {
int Render::SendKeyCommand(int key_code, bool is_down) {
RemoteAction remote_action;
remote_action.type = ControlType::keyboard;
@@ -543,3 +545,4 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size,
props->net_traffic_stats_ = *net_traffic_stats;
}
}
} // namespace crossdesk

View File

@@ -3,6 +3,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
int CountDigits(int number) {
if (number == 0) return 1;
return (int)std::floor(std::log10(std::abs(number))) + 1;
@@ -324,3 +326,4 @@ int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
return 0;
}
} // namespace crossdesk

View File

@@ -1,6 +1,8 @@
#include "localization.h"
#include "render.h"
namespace crossdesk {
int Render::StatusBar() {
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
static bool a, b, c, d, e;
@@ -36,3 +38,4 @@ int Render::StatusBar() {
ImGui::EndChild();
return 0;
}
} // namespace crossdesk

View File

@@ -4,6 +4,8 @@
#define BUTTON_PADDING 36.0f
namespace crossdesk {
int Render::TitleBar(bool main_window) {
ImGui::PushStyleColor(ImGuiCol_MenuBarBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
@@ -172,3 +174,4 @@ int Render::TitleBar(bool main_window) {
ImGui::PopStyleColor();
return 0;
}
} // namespace crossdesk

View File

@@ -4,6 +4,8 @@
#include "localization.h"
namespace crossdesk {
// callback for the message-only window that handles tray icon messages
static LRESULT CALLBACK MsgWndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam) {
@@ -110,3 +112,4 @@ bool WinTray::HandleTrayMessage(MSG* msg) {
}
return true;
}
} // namespace crossdesk

View File

@@ -14,6 +14,8 @@
#define WM_TRAY_CALLBACK (WM_USER + 1)
namespace crossdesk {
class WinTray {
public:
WinTray(HWND app_hwnd, HICON icon, const std::wstring& tooltip,
@@ -32,5 +34,5 @@ class WinTray {
int language_index_;
NOTIFYICONDATA nid_;
};
} // namespace crossdesk
#endif

View File

@@ -3,9 +3,11 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
int Render::AboutWindow() {
if (show_about_window_) {
const ImGuiViewport *viewport = ImGui::GetMainViewport();
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(ImVec2(
(viewport->WorkSize.x - viewport->WorkPos.x - about_window_width_) / 2,
@@ -59,3 +61,4 @@ int Render::AboutWindow() {
}
return 0;
}
} // namespace crossdesk

View File

@@ -3,9 +3,11 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
bool Render::ConnectionStatusWindow(
std::shared_ptr<SubStreamWindowProperties> &props) {
const ImGuiViewport *viewport = ImGui::GetMainViewport();
std::shared_ptr<SubStreamWindowProperties>& props) {
const ImGuiViewport* viewport = ImGui::GetMainViewport();
bool ret_flag = false;
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
connection_status_window_width_) /
@@ -169,3 +171,4 @@ bool Render::ConnectionStatusWindow(
return ret_flag;
}
} // namespace crossdesk

View File

@@ -1,7 +1,9 @@
#include "rd_log.h"
#include "render.h"
int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) {
namespace crossdesk {
int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
double time_duration =
ImGui::GetTime() - props->control_bar_button_pressed_time_;
if (props->control_window_width_is_changing_) {
@@ -221,3 +223,4 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) {
return 0;
}
} // namespace crossdesk

View File

@@ -3,6 +3,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
int Render::SettingWindow() {
if (show_settings_window_) {
if (settings_window_pos_reset_) {
@@ -391,3 +393,4 @@ int Render::SettingWindow() {
return 0;
}
} // namespace crossdesk

View File

@@ -2,6 +2,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
int Render::MainWindow() {
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
@@ -47,3 +49,4 @@ int Render::MainWindow() {
return 0;
}
} // namespace crossdesk

View File

@@ -10,6 +10,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
std::vector<std::string> GetRootEntries() {
std::vector<std::string> roots;
#ifdef _WIN32
@@ -319,3 +321,4 @@ int Render::SelfHostedServerWindow() {
return 0;
}
} // namespace crossdesk

View File

@@ -2,6 +2,8 @@
#include "rd_log.h"
#include "render.h"
namespace crossdesk {
void Render::DrawConnectionStatusText(
std::shared_ptr<SubStreamWindowProperties>& props) {
std::string text;
@@ -200,3 +202,4 @@ int Render::StreamWindow() {
return 0;
}
} // namespace crossdesk

View File

@@ -3,6 +3,8 @@
#include <atomic>
#include <filesystem>
namespace crossdesk {
namespace {
std::string g_log_dir = "logs";
@@ -60,3 +62,4 @@ std::shared_ptr<spdlog::logger> get_logger() {
return g_logger;
}
} // namespace crossdesk

View File

@@ -25,6 +25,8 @@
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
namespace crossdesk {
constexpr auto LOGGER_NAME = "crossdesk";
void InitLogger(const std::string& log_dir);
@@ -35,5 +37,5 @@ std::shared_ptr<spdlog::logger> get_logger();
#define LOG_WARN(...) SPDLOG_LOGGER_WARN(get_logger(), __VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_LOGGER_ERROR(get_logger(), __VA_ARGS__)
#define LOG_FATAL(...) SPDLOG_LOGGER_CRITICAL(get_logger(), __VA_ARGS__)
} // namespace crossdesk
#endif

View File

@@ -2,6 +2,8 @@
#include <cstdlib>
namespace crossdesk {
PathManager::PathManager(const std::string& app_name) : app_name_(app_name) {}
std::filesystem::path PathManager::GetConfigPath() {
@@ -89,3 +91,4 @@ std::filesystem::path PathManager::GetEnvOrDefault(const char* env_var,
return std::filesystem::path(def);
}
} // namespace crossdesk

View File

@@ -14,6 +14,8 @@
#include <windows.h>
#endif
namespace crossdesk {
class PathManager {
public:
explicit PathManager(const std::string& app_name);
@@ -40,5 +42,5 @@ class PathManager {
private:
std::string app_name_;
};
} // namespace crossdesk
#endif

View File

@@ -6,6 +6,8 @@
#include "libyuv.h"
#include "rd_log.h"
namespace crossdesk {
ScreenCapturerX11::ScreenCapturerX11() {}
ScreenCapturerX11::~ScreenCapturerX11() { Destroy(); }
@@ -172,3 +174,4 @@ void ScreenCapturerX11::OnFrame() {
XDestroyImage(image);
}
} // namespace crossdesk

View File

@@ -20,6 +20,8 @@
#include "screen_capturer.h"
namespace crossdesk {
class ScreenCapturerX11 : public ScreenCapturer {
public:
ScreenCapturerX11();
@@ -60,5 +62,5 @@ class ScreenCapturerX11 : public ScreenCapturer {
std::vector<uint8_t> y_plane_;
std::vector<uint8_t> uv_plane_;
};
} // namespace crossdesk
#endif

View File

@@ -2,6 +2,8 @@
#include "rd_log.h"
namespace crossdesk {
ScreenCapturerSck::ScreenCapturerSck() {}
ScreenCapturerSck::~ScreenCapturerSck() {}
@@ -71,3 +73,4 @@ std::vector<DisplayInfo> ScreenCapturerSck::GetDisplayInfoList() {
void ScreenCapturerSck::OnFrame() {}
void ScreenCapturerSck::CleanUp() {}
} // namespace crossdesk

View File

@@ -16,6 +16,8 @@
#include "screen_capturer.h"
namespace crossdesk {
class ScreenCapturerSck : public ScreenCapturer {
public:
ScreenCapturerSck();
@@ -55,5 +57,5 @@ class ScreenCapturerSck : public ScreenCapturer {
private:
std::unique_ptr<ScreenCapturer> screen_capturer_sck_impl_;
};
} // namespace crossdesk
#endif

View File

@@ -22,9 +22,12 @@
#include "display_info.h"
#include "rd_log.h"
static const int kFullDesktopScreenId = -1;
using namespace crossdesk;
class ScreenCapturerSckImpl;
static const int kFullDesktopScreenId = -1;
// The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture
// was reported to be broken before macOS 13 - see http://crbug.com/40234870.
// Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were
@@ -424,10 +427,6 @@ void ScreenCapturerSckImpl::StartOrReconfigureCapturer() {
[SCShareableContent getShareableContentWithCompletionHandler:handler];
}
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
return std::make_unique<ScreenCapturerSckImpl>();
}
@implementation SckHelper {
// This lock is to prevent the capturer being destroyed while an instance
// method is still running on another thread.
@@ -486,3 +485,7 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
}
@end
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
return std::make_unique<ScreenCapturerSckImpl>();
}

View File

@@ -11,6 +11,8 @@
#include "display_info.h"
namespace crossdesk {
class ScreenCapturer {
public:
typedef std::function<void(unsigned char*, int, int, int, const char*)>
@@ -30,5 +32,5 @@ class ScreenCapturer {
virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0;
virtual int SwitchTo(int monitor_index) = 0;
};
} // namespace crossdesk
#endif

View File

@@ -16,6 +16,8 @@
#include "screen_capturer_sck.h"
#endif
namespace crossdesk {
class ScreenCapturerFactory {
public:
virtual ~ScreenCapturerFactory() {}
@@ -34,5 +36,5 @@ class ScreenCapturerFactory {
#endif
}
};
} // namespace crossdesk
#endif

View File

@@ -10,9 +10,11 @@
#include "libyuv.h"
#include "rd_log.h"
namespace crossdesk {
static std::vector<DisplayInfo> gs_display_list;
std::string WideToUtf8(const wchar_t *wideStr) {
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);
@@ -31,14 +33,14 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) {
gs_display_list.insert(
gs_display_list.begin(),
{(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
{(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});
*(HMONITOR *)data = hmonitor;
*(HMONITOR*)data = hmonitor;
} else {
gs_display_list.push_back(DisplayInfo(
(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
(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));
@@ -81,7 +83,7 @@ bool ScreenCapturerWgc::IsWgcSupported() {
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
return winrt::Windows::Foundation::Metadata::ApiInformation::
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
} catch (const winrt::hresult_error &) {
} catch (const winrt::hresult_error&) {
return false;
} catch (...) {
return false;
@@ -115,7 +117,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) {
}
for (int i = 0; i < display_info_list_.size(); i++) {
const auto &display = display_info_list_[i];
const auto& display = display_info_list_[i];
LOG_INFO(
"index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - "
"({}, {})",
@@ -243,16 +245,16 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) {
return 0;
}
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame,
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame& frame,
int id) {
if (on_data_) {
if (!nv12_frame_) {
nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2];
}
libyuv::ARGBToNV12((const uint8_t *)frame.data, frame.width * 4,
(uint8_t *)nv12_frame_, frame.width,
(uint8_t *)(nv12_frame_ + frame.width * frame.height),
libyuv::ARGBToNV12((const uint8_t*)frame.data, frame.width * 4,
(uint8_t*)nv12_frame_, frame.width,
(uint8_t*)(nv12_frame_ + frame.width * frame.height),
frame.width, frame.width, frame.height);
on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width,
@@ -262,7 +264,7 @@ void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame,
void ScreenCapturerWgc::CleanUp() {
if (inited_) {
for (auto &session : sessions_) {
for (auto& session : sessions_) {
if (session.session_) {
session.session_->Stop();
}
@@ -270,3 +272,4 @@ void ScreenCapturerWgc::CleanUp() {
sessions_.clear();
}
}
} // namespace crossdesk

View File

@@ -11,6 +11,8 @@
#include "wgc_session.h"
#include "wgc_session_impl.h"
namespace crossdesk {
class ScreenCapturerWgc : public ScreenCapturer,
public WgcSession::wgc_session_observer {
public:
@@ -64,5 +66,5 @@ class ScreenCapturerWgc : public ScreenCapturer,
unsigned char* nv12_frame_ = nullptr;
unsigned char* nv12_frame_scaled_ = nullptr;
};
} // namespace crossdesk
#endif

View File

@@ -3,6 +3,8 @@
#include <Windows.h>
namespace crossdesk {
class WgcSession {
public:
struct wgc_session_frame {
@@ -10,13 +12,13 @@ class WgcSession {
unsigned int height;
unsigned int row_pitch;
const unsigned char *data;
const unsigned char* data;
};
class wgc_session_observer {
public:
virtual ~wgc_session_observer() {}
virtual void OnFrame(const wgc_session_frame &frame, int id) = 0;
virtual void OnFrame(const wgc_session_frame& frame, int id) = 0;
};
public:
@@ -25,7 +27,7 @@ class WgcSession {
virtual int Initialize(HWND hwnd) = 0;
virtual int Initialize(HMONITOR hmonitor) = 0;
virtual void RegisterObserver(wgc_session_observer *observer) = 0;
virtual void RegisterObserver(wgc_session_observer* observer) = 0;
virtual int Start() = 0;
virtual int Stop() = 0;
@@ -33,7 +35,7 @@ class WgcSession {
virtual int Pause() = 0;
virtual int Resume() = 0;
virtual ~WgcSession(){};
virtual ~WgcSession() {};
};
} // namespace crossdesk
#endif

View File

@@ -18,9 +18,11 @@
throw winrt::hresult_error(RO_E_CLOSED); \
}
namespace crossdesk {
extern "C" {
HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(
::IDXGIDevice *dxgiDevice, ::IInspectable **graphicsDevice);
::IDXGIDevice* dxgiDevice, ::IInspectable** graphicsDevice);
}
WgcSessionImpl::WgcSessionImpl(int id) : id_(id) {}
@@ -48,7 +50,7 @@ int WgcSessionImpl::Initialize(HMONITOR hmonitor) {
return Initialize();
}
void WgcSessionImpl::RegisterObserver(wgc_session_observer *observer) {
void WgcSessionImpl::RegisterObserver(wgc_session_observer* observer) {
std::lock_guard locker(lock_);
observer_ = observer;
}
@@ -175,7 +177,7 @@ auto WgcSessionImpl::CreateCaptureItemForWindow(HWND hwnd) {
interop_factory->CreateForWindow(
hwnd,
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
reinterpret_cast<void **>(winrt::put_abi(item)));
reinterpret_cast<void**>(winrt::put_abi(item)));
return item;
}
@@ -187,7 +189,7 @@ auto WgcSessionImpl::CreateCaptureItemForMonitor(HMONITOR hmonitor) {
interop_factory->CreateForMonitor(
hmonitor,
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
reinterpret_cast<void **>(winrt::put_abi(item)));
reinterpret_cast<void**>(winrt::put_abi(item)));
return item;
}
@@ -216,8 +218,8 @@ HRESULT WgcSessionImpl::CreateMappedTexture(
}
void WgcSessionImpl::OnFrame(
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender,
[[maybe_unused]] winrt::Windows::Foundation::IInspectable const &args) {
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const& sender,
[[maybe_unused]] winrt::Windows::Foundation::IInspectable const& args) {
std::lock_guard locker(lock_);
auto is_new_size = false;
@@ -268,8 +270,8 @@ void WgcSessionImpl::OnFrame(
wgc_session_frame{static_cast<unsigned int>(frame_size.Width),
static_cast<unsigned int>(frame_size.Height),
map_result.RowPitch,
const_cast<const unsigned char *>(
(unsigned char *)map_result.pData)},
const_cast<const unsigned char*>(
(unsigned char*)map_result.pData)},
id_);
}
@@ -286,8 +288,8 @@ void WgcSessionImpl::OnFrame(
}
void WgcSessionImpl::OnClosed(
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
winrt::Windows::Foundation::IInspectable const &) {
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&,
winrt::Windows::Foundation::IInspectable const&) {
OutputDebugStringW(L"WgcSessionImpl::OnClosed");
}
@@ -376,3 +378,4 @@ LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM w_param,
// ::CloseWindow(hwnd_);
// ::DestroyWindow(hwnd_);
// }
} // namespace crossdesk

View File

@@ -10,15 +10,17 @@
#include "wgc_session.h"
namespace crossdesk {
class WgcSessionImpl : public WgcSession {
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
IDirect3DDxgiInterfaceAccess : ::IUnknown {
virtual HRESULT __stdcall GetInterface(GUID const &id, void **object) = 0;
virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
};
template <typename T>
inline auto GetDXGIInterfaceFromObject(
winrt::Windows::Foundation::IInspectable const &object) {
winrt::Windows::Foundation::IInspectable const& object) {
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
winrt::com_ptr<T> result;
winrt::check_hresult(
@@ -44,7 +46,7 @@ class WgcSessionImpl : public WgcSession {
int Initialize(HWND hwnd) override;
int Initialize(HMONITOR hmonitor) override;
void RegisterObserver(wgc_session_observer *observer) override;
void RegisterObserver(wgc_session_observer* observer) override;
int Start() override;
int Stop() override;
@@ -60,11 +62,11 @@ class WgcSessionImpl : public WgcSession {
HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture,
unsigned int width = 0, unsigned int height = 0);
void OnFrame(
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const
&sender,
winrt::Windows::Foundation::IInspectable const &args);
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
winrt::Windows::Foundation::IInspectable const &);
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const&
sender,
winrt::Windows::Foundation::IInspectable const& args);
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&,
winrt::Windows::Foundation::IInspectable const&);
int Initialize();
void CleanUp();
@@ -78,7 +80,7 @@ class WgcSessionImpl : public WgcSession {
bool is_running_ = false;
bool is_paused_ = false;
wgc_session_observer *observer_ = nullptr;
wgc_session_observer* observer_ = nullptr;
// wgc
winrt::Windows::Graphics::Capture::GraphicsCaptureItem capture_item_{nullptr};
@@ -113,5 +115,5 @@ class WgcSessionImpl : public WgcSession {
// access->GetInterface(winrt::guid_of<T>(), result.put_void()));
// return result;
// }
} // namespace crossdesk
#endif

View File

@@ -9,6 +9,8 @@
#include "rd_log.h"
namespace crossdesk {
constexpr int kSampleRate = 48000;
constexpr pa_sample_format_t kFormat = PA_SAMPLE_S16LE;
constexpr int kChannels = 1;
@@ -266,3 +268,4 @@ int SpeakerCapturerLinux::Resume() {
paused_ = false;
return 0;
}
} // namespace crossdesk

View File

@@ -18,6 +18,8 @@
#include "speaker_capturer.h"
namespace crossdesk {
class SpeakerCapturerLinux : public SpeakerCapturer {
public:
SpeakerCapturerLinux();
@@ -50,5 +52,5 @@ class SpeakerCapturerLinux : public SpeakerCapturer {
std::mutex state_mtx_;
std::vector<uint8_t> frame_cache_;
};
} // namespace crossdesk
#endif

View File

@@ -12,6 +12,8 @@
#include "speaker_capturer.h"
namespace crossdesk {
class SpeakerCapturerMacosx : public SpeakerCapturer {
public:
SpeakerCapturerMacosx();
@@ -33,5 +35,5 @@ class SpeakerCapturerMacosx : public SpeakerCapturer {
class Impl;
Impl* impl_ = nullptr;
};
} // namespace crossdesk
#endif

View File

@@ -5,13 +5,17 @@
#include "rd_log.h"
#include "speaker_capturer_macosx.h"
namespace crossdesk {
class SpeakerCapturerMacosx;
}
@interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput>
@property(nonatomic, assign) SpeakerCapturerMacosx* owner;
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner;
@property(nonatomic, assign) crossdesk::SpeakerCapturerMacosx* owner;
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner;
@end
@implementation SpeakerCaptureDelegate
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner {
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner {
self = [super init];
if (self) {
_owner = owner;
@@ -22,7 +26,8 @@
- (void)stream:(SCStream*)stream
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
ofType:(SCStreamOutputType)type {
if (type == SCStreamOutputTypeAudio) {
if (type != SCStreamOutputTypeAudio) return;
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
size_t length = CMBlockBufferGetDataLength(blockBuffer);
char* dataPtr = NULL;
@@ -33,50 +38,8 @@
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
std::vector<short> out_pcm16;
if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) {
int channels = asbd->mChannelsPerFrame;
int samples = (int)(length / sizeof(float));
float* floatData = (float*)dataPtr;
std::vector<short> pcm16(samples);
for (int i = 0; i < samples; ++i) {
float v = floatData[i];
if (v > 1.0f) v = 1.0f;
if (v < -1.0f) v = -1.0f;
pcm16[i] = (short)(v * 32767.0f);
}
if (channels > 1) {
int mono_samples = samples / channels;
out_pcm16.resize(mono_samples);
for (int i = 0; i < mono_samples; ++i) {
int sum = 0;
for (int c = 0; c < channels; ++c) {
sum += pcm16[i * channels + c];
}
out_pcm16[i] = sum / channels;
}
} else {
out_pcm16 = std::move(pcm16);
}
} else if (asbd->mBitsPerChannel == 16) {
int channels = asbd->mChannelsPerFrame;
int samples = (int)(length / 2);
short* src = (short*)dataPtr;
if (channels > 1) {
int mono_samples = samples / channels;
out_pcm16.resize(mono_samples);
for (int i = 0; i < mono_samples; ++i) {
int sum = 0;
for (int c = 0; c < channels; ++c) {
sum += src[i * channels + c];
}
out_pcm16[i] = sum / channels;
}
} else {
out_pcm16.assign(src, src + samples);
}
}
// ... 数据转换逻辑保持不变 ...
// 调用回调
size_t frame_bytes = 960; // 480 * 2
size_t total_bytes = out_pcm16.size() * sizeof(short);
unsigned char* p = (unsigned char*)out_pcm16.data();
@@ -84,10 +47,11 @@
_owner->cb_(p + offset, frame_bytes, "audio");
}
}
}
}
@end
namespace crossdesk {
class SpeakerCapturerMacosx::Impl {
public:
SCStreamConfiguration* config = nil;
@@ -262,3 +226,4 @@ int SpeakerCapturerMacosx::Destroy() {
int SpeakerCapturerMacosx::Pause() { return 0; }
int SpeakerCapturerMacosx::Resume() { return Start(); }
} // namespace crossdesk

View File

@@ -9,9 +9,11 @@
#include <functional>
namespace crossdesk {
class SpeakerCapturer {
public:
typedef std::function<void(unsigned char *, size_t, const char *)>
typedef std::function<void(unsigned char*, size_t, const char*)>
speaker_data_cb;
public:
@@ -23,5 +25,5 @@ class SpeakerCapturer {
virtual int Start() = 0;
virtual int Stop() = 0;
};
} // namespace crossdesk
#endif

View File

@@ -15,6 +15,8 @@
#include "speaker_capturer_macosx.h"
#endif
namespace crossdesk {
class SpeakerCapturerFactory {
public:
virtual ~SpeakerCapturerFactory() {}
@@ -32,5 +34,5 @@ class SpeakerCapturerFactory {
#endif
}
};
} // namespace crossdesk
#endif

View File

@@ -7,6 +7,8 @@
#define SAVE_AUDIO_FILE 0
namespace crossdesk {
static ma_device_config device_config_;
static ma_device device_;
static ma_format format_ = ma_format_s16;
@@ -99,3 +101,4 @@ int SpeakerCapturerWasapi::Destroy() {
}
int SpeakerCapturerWasapi::Pause() { return 0; }
} // namespace crossdesk

View File

@@ -9,6 +9,8 @@
#include "speaker_capturer.h"
namespace crossdesk {
class SpeakerCapturerWasapi : public SpeakerCapturer {
public:
SpeakerCapturerWasapi();
@@ -31,5 +33,5 @@ class SpeakerCapturerWasapi : public SpeakerCapturer {
private:
bool inited_ = false;
};
} // namespace crossdesk
#endif

View File

@@ -21,7 +21,7 @@
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
static std::string test;
namespace crossdesk {
bool LoadTextureFromMemory(const void* data, size_t data_size,
SDL_Renderer* renderer, SDL_Texture** out_texture,
@@ -430,3 +430,4 @@ std::string Thumbnail::AES_decrypt(const std::string& ciphertext,
return std::string(reinterpret_cast<char*>(plaintext), plaintext_len);
}
} // namespace crossdesk

View File

@@ -14,6 +14,8 @@
#include <unordered_map>
#include <vector>
namespace crossdesk {
class Thumbnail {
public:
struct RecentConnection {
@@ -83,5 +85,5 @@ class Thumbnail {
unsigned char ciphertext_[64];
unsigned char decryptedtext_[64];
};
} // namespace crossdesk
#endif

View File

@@ -1,194 +0,0 @@
add_rules("mode.debug", "mode.release")
add_rules("utils.install.cmake_importfiles")
set_languages("cxx14")
option("dx9", {showmenu = true, default = false})
option("dx10", {showmenu = true, default = false})
option("dx11", {showmenu = true, default = false})
option("dx12", {showmenu = true, default = false})
option("glfw", {showmenu = true, default = false})
option("opengl2", {showmenu = true, default = false})
option("opengl3", {showmenu = true, default = false})
option("glad", {showmenu = true, default = false})
option("sdl2", {showmenu = true, default = false})
option("sdl2_renderer", {showmenu = true, default = false})
option("sdl3", {showmenu = true, default = false})
option("sdl3_renderer", {showmenu = true, default = false})
option("sdl3_gpu", {showmenu = true, default = false})
option("vulkan", {showmenu = true, default = false})
option("win32", {showmenu = true, default = false})
option("osx", {showmenu = true, default = false})
option("wgpu", {showmenu = true, default = false})
option("freetype", {showmenu = true, default = false})
option("user_config", {showmenu = true, default = nil, type = "string"})
option("wchar32", {showmenu = true, default = false})
if has_config("glfw") then
add_requires("glfw")
end
if has_config("glad") then
add_requires("glad")
end
if has_config("sdl2_renderer") then
add_requires("libsdl2 >=2.0.17")
elseif has_config("sdl2") then
add_requires("libsdl2")
end
if has_config("sdl3") or has_config("sdl3_renderer") or has_config("sdl3_gpu") then
add_requires("libsdl3")
end
if has_config("vulkan") then
add_requires("vulkan-headers")
end
if has_config("wgpu") then
add_requires("wgpu-native")
end
if has_config("freetype") then
add_requires("freetype")
end
target("imgui")
set_kind("$(kind)")
add_files("*.cpp", "misc/cpp/*.cpp")
add_headerfiles("*.h", "(misc/cpp/*.h)")
add_includedirs(".", "misc/cpp")
if is_kind("shared") and is_plat("windows", "mingw") then
add_defines("IMGUI_API=__declspec(dllexport)")
end
if has_config("dx9") then
add_files("backends/imgui_impl_dx9.cpp")
add_headerfiles("(backends/imgui_impl_dx9.h)")
end
if has_config("dx10") then
add_files("backends/imgui_impl_dx10.cpp")
add_headerfiles("(backends/imgui_impl_dx10.h)")
end
if has_config("dx11") then
add_files("backends/imgui_impl_dx11.cpp")
add_headerfiles("(backends/imgui_impl_dx11.h)")
end
if has_config("dx12") then
add_files("backends/imgui_impl_dx12.cpp")
add_headerfiles("(backends/imgui_impl_dx12.h)")
end
if has_config("glfw") then
add_files("backends/imgui_impl_glfw.cpp")
add_headerfiles("(backends/imgui_impl_glfw.h)")
add_packages("glfw")
end
if has_config("opengl2") then
add_files("backends/imgui_impl_opengl2.cpp")
add_headerfiles("(backends/imgui_impl_opengl2.h)")
end
if has_config("opengl3") then
add_files("backends/imgui_impl_opengl3.cpp")
add_headerfiles("(backends/imgui_impl_opengl3.h)")
if has_config("glad") then
add_defines("IMGUI_IMPL_OPENGL_LOADER_GLAD")
add_packages("glad")
else
add_headerfiles("(backends/imgui_impl_opengl3_loader.h)")
end
end
if has_config("sdl2") then
if os.exists("backends/imgui_impl_sdl2.cpp") then
add_files("backends/imgui_impl_sdl2.cpp")
add_headerfiles("(backends/imgui_impl_sdl2.h)")
else
add_files("backends/imgui_impl_sdl.cpp")
add_headerfiles("(backends/imgui_impl_sdl.h)")
end
add_packages("libsdl2")
end
if has_config("sdl2_renderer") then
if os.exists("backends/imgui_impl_sdlrenderer2.cpp") then
add_files("backends/imgui_impl_sdlrenderer2.cpp")
add_headerfiles("(backends/imgui_impl_sdlrenderer2.h)")
else
add_files("backends/imgui_impl_sdlrenderer.cpp")
add_headerfiles("(backends/imgui_impl_sdlrenderer.h)")
end
add_packages("libsdl2")
end
if has_config("sdl3") then
add_files("backends/imgui_impl_sdl3.cpp")
add_headerfiles("(backends/imgui_impl_sdl3.h)")
add_packages("libsdl3")
end
if has_config("sdl3_renderer") then
add_files("backends/imgui_impl_sdlrenderer3.cpp")
add_headerfiles("(backends/imgui_impl_sdlrenderer3.h)")
add_packages("libsdl3")
end
if has_config("sdl3_gpu") then
add_files("backends/imgui_impl_sdlgpu3.cpp")
add_headerfiles("backends/imgui_impl_sdlgpu3.h","backends/imgui_impl_sdlgpu3_shaders.h")
add_packages("libsdl3")
end
if has_config("vulkan") then
add_files("backends/imgui_impl_vulkan.cpp")
add_headerfiles("(backends/imgui_impl_vulkan.h)")
add_packages("vulkan-headers")
end
if has_config("win32") then
add_files("backends/imgui_impl_win32.cpp")
add_headerfiles("(backends/imgui_impl_win32.h)")
end
if has_config("osx") then
add_frameworks("Cocoa", "Carbon", "GameController")
add_files("backends/imgui_impl_osx.mm")
add_headerfiles("(backends/imgui_impl_osx.h)")
end
if has_config("wgpu") then
add_files("backends/imgui_impl_wgpu.cpp")
add_headerfiles("(backends/imgui_impl_wgpu.h)")
add_packages("wgpu-native")
end
if has_config("freetype") then
add_files("misc/freetype/imgui_freetype.cpp")
add_headerfiles("misc/freetype/imgui_freetype.h")
add_packages("freetype")
add_defines("IMGUI_ENABLE_FREETYPE")
end
if has_config("user_config") then
local user_config = get_config("user_config")
add_defines("IMGUI_USER_CONFIG=\"".. user_config .."\"")
end
if has_config("wchar32") then
add_defines("IMGUI_USE_WCHAR32")
end
after_install(function (target)
local config_file = path.join(target:installdir(), "include/imconfig.h")
if has_config("wchar32") then
io.gsub(config_file, "//#define IMGUI_USE_WCHAR32", "#define IMGUI_USE_WCHAR32")
end
if has_config("freetype") then
io.gsub(config_file, "//#define IMGUI_ENABLE_FREETYPE", "#define IMGUI_ENABLE_FREETYPE")
end
end)

View File

@@ -1,227 +0,0 @@
package("imgui")
set_homepage("https://github.com/ocornut/imgui")
set_description("Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies")
set_license("MIT")
add_urls("https://github.com/ocornut/imgui/archive/refs/tags/$(version).tar.gz")
add_urls("https://github.com/ocornut/imgui.git", {alias = "git"})
-- don't forget to add the docking versions as well
add_versions("v1.92.0", "42250c45df2736bcef867ae4ff404d138e5135cd36466c63143b1ea3b1c81091")
add_versions("v1.91.9", "3872a5f90df78fced023c1945f4466b654fd74573370b77b17742149763a7a7c")
add_versions("v1.91.8", "db3a2e02bfd6c269adf0968950573053d002f40bdfb9ef2e4a90bce804b0f286")
add_versions("v1.91.7", "2001dab4bdd7d178d8277d3b17c40aa1ff1e76e2ccac5e7ab8c6daf9756312c2")
add_versions("v1.91.6", "c5fbc5dcab1d46064001c3b84d7a88812985cde7e0e9ced03f5677bec1ba502a")
add_versions("v1.91.5", "2aa2d169c569368439e5d5667e0796d09ca5cc6432965ce082e516937d7db254")
add_versions("v1.91.4", "a455c28d987c78ddf56aab98ce0ff0fda791a23a2ec88ade46dd106b837f0923")
add_versions("v1.91.3", "29949d7b300c30565fbcd66398100235b63aa373acfee0b76853a7aeacd1be28")
add_versions("v1.91.2", "a3c4fd857a0a48f6edad3e25de68fa1e96d2437f1665039714d1de9ad579b8d0")
add_versions("v1.91.1", "2c13a8909f75222c836abc9b3f60cef31c445f3f41f95d8242118ea789d145ca")
add_versions("v1.91.0", "6e62c87252e6b3725ba478a1c04dc604aa0aaeec78fedcf4011f1e52548f4cc9")
add_versions("v1.90.9", "04943919721e874ac75a2f45e6eb6c0224395034667bf508923388afda5a50bf")
add_versions("v1.90.8", "f606b4fb406aa0f8dad36d4a9dd3d6f0fd39f5f0693e7468abc02d545fb505ae")
add_versions("v1.90.7", "872574217643d4ad7e9e6df420bb8d9e0d468fb90641c2bf50fd61745e05de99")
add_versions("v1.90.6", "70b4b05ac0938e82b4d5b8d59480d3e2ca63ca570dfb88c55023831f387237ad")
add_versions("v1.90.5", "e94b48dba7311c85ba8e3e6fe7c734d76a0eed21b2b42c5180fd5706d1562241")
add_versions("v1.90.4", "5d9dc738af74efa357f2a9fc39fe4a28d29ef1dfc725dd2977ccf3f3194e996e")
add_versions("v1.90.3", "40b302d01092c9393373b372fe07ea33ac69e9491893ebab3bf952b2c1f5fd23")
add_versions("v1.90.2", "452d1c11e5c4b4dfcca272915644a65f1c076498e8318b141ca75cd30470dd68")
add_versions("v1.90.1", "21dcc985bb2ae8fe48047c86135dbc438d6980a8f2e08babbda5be820592f282")
add_versions("v1.90", "170986e6a4b83d165bfc1d33c2c5a5bc2d67e5b97176287485c51a2299249296")
add_versions("v1.89.9", "1acc27a778b71d859878121a3f7b287cd81c29d720893d2b2bf74455bf9d52d6")
add_versions("v1.89.8", "6680ccc32430009a8204291b1268b2367d964bd6d1b08a4e0358a017eb8e8c9e")
add_versions("v1.89.7", "115ee9e242af98a884302ac0f6ca3b2b26b1f10c660205f5e7ad9f1d1c96d269")
add_versions("v1.89.6", "e95d1cba1481e66386acda3e7da19cd738da86c6c2a140a48fa55046e5f6e208")
add_versions("v1.89.5", "eab371005c86dd029523a0c4ba757840787163740d45c1f4e5a110eb21820546")
add_versions("v1.89.4", "69f1e83adcab3fdd27b522f5075f407361b0d3875e3522b13d33bc2ae2c7d48c")
add_versions("v1.89.3", "3b665fadd5580b7ef494d5d8bb1c12b2ec53ee723034caf43332956381f5d631")
add_versions("v1.89", "4038b05bd44c889cf40be999656d3871a0559916708cb52a6ae2fa6fa35c5c60")
add_versions("v1.88", "9f14c788aee15b777051e48f868c5d4d959bd679fc5050e3d2a29de80d8fd32e")
add_versions("v1.87", "b54ceb35bda38766e36b87c25edf7a1cd8fd2cb8c485b245aedca6fb85645a20")
add_versions("v1.86", "6ba6ae8425a19bc52c5e067702c48b70e4403cd339cba02073a462730a63e825")
add_versions("v1.85", "7ed49d1f4573004fa725a70642aaddd3e06bb57fcfe1c1a49ac6574a3e895a77")
add_versions("v1.84.2", "35cb5ca0fb42cb77604d4f908553f6ef3346ceec4fcd0189675bdfb764f62b9b")
add_versions("v1.84.1", "292ab54cfc328c80d63a3315a242a4785d7c1cf7689fbb3d70da39b34db071ea")
add_versions("v1.83", "ccf3e54b8d1fa30dd35682fc4f50f5d2fe340b8e29e08de71287d0452d8cc3ff")
add_versions("v1.82", "fefa2804bd55f3d25b134af08c0e1f86d4d059ac94cef3ee7bd21e2f194e5ce5")
add_versions("v1.81", "f7c619e03a06c0f25e8f47262dbc32d61fd033d2c91796812bf0f8c94fca78fb")
add_versions("v1.80", "d7e4e1c7233409018437a646680316040e6977b9a635c02da93d172baad94ce9")
add_versions("v1.79", "f1908501f6dc6db8a4d572c29259847f6f882684b10488d3a8d2da31744cd0a4")
add_versions("v1.78", "f70bbb17581ee2bd42fda526d9c3dc1a5165f3847ff047483d4d7980e166f9a3")
add_versions("v1.77", "c0dae830025d4a1a169df97409709f40d9dfa19f8fc96b550052224cbb238fa8")
add_versions("v1.76", "e482dda81330d38c87bd81597cacaa89f05e20ed2c4c4a93a64322e97565f6dc")
add_versions("v1.75", "1023227fae4cf9c8032f56afcaea8902e9bfaad6d9094d6e48fb8f3903c7b866")
add_versions("git:v1.92.0-docking", "v1.92.0-docking")
add_versions("git:v1.91.9-docking", "v1.91.9-docking")
add_versions("git:v1.91.8-docking", "v1.91.8-docking")
add_versions("git:v1.91.7-docking", "v1.91.7-docking")
add_versions("git:v1.91.6-docking", "v1.91.6-docking")
add_versions("git:v1.91.5-docking", "v1.91.5-docking")
add_versions("git:v1.91.4-docking", "v1.91.4-docking")
add_versions("git:v1.91.3-docking", "v1.91.3-docking")
add_versions("git:v1.91.2-docking", "v1.91.2-docking")
add_versions("git:v1.91.1-docking", "v1.91.1-docking")
add_versions("git:v1.91.0-docking", "v1.91.0-docking")
add_versions("git:v1.90.9-docking", "v1.90.9-docking")
add_versions("git:v1.90.8-docking", "v1.90.8-docking")
add_versions("git:v1.90.7-docking", "v1.90.7-docking")
add_versions("git:v1.90.6-docking", "v1.90.6-docking")
add_versions("git:v1.90.5-docking", "v1.90.5-docking")
add_versions("git:v1.90.4-docking", "v1.90.4-docking")
add_versions("git:v1.90.3-docking", "v1.90.3-docking")
add_versions("git:v1.90.2-docking", "v1.90.2-docking")
add_versions("git:v1.90.1-docking", "v1.90.1-docking")
add_versions("git:v1.90-docking", "v1.90-docking")
add_versions("git:v1.89.9-docking", "v1.89.9-docking")
add_versions("git:v1.89.8-docking", "v1.89.8-docking")
add_versions("git:v1.89.7-docking", "v1.89.7-docking")
add_versions("git:v1.89.6-docking", "823a1385a269d923d35b82b2f470f3ae1fa8b5a3")
add_versions("git:v1.89.5-docking", "0ea3b87bd63ecbf359585b7c235839146e84dedb")
add_versions("git:v1.89.4-docking", "9e30fb0ec1b44dc1b041db6bdd53b130b2a18509")
add_versions("git:v1.89.3-docking", "192196711a7d0d7c2d60454d42654cf090498a74")
add_versions("git:v1.89-docking", "94e850fd6ff9eceb98fda3147e3ffd4781ad2dc7")
add_versions("git:v1.88-docking", "9cd9c2eff99877a3f10a7f9c2a3a5b9c15ea36c6")
add_versions("git:v1.87-docking", "1ee252772ae9c0a971d06257bb5c89f628fa696a")
add_versions("git:v1.85-docking", "dc8c3618e8f8e2dada23daa1aa237626af341fd8")
add_versions("git:v1.83-docking", "80b5fb51edba2fd3dea76ec3e88153e2492243d1")
-- Fix conflicting IMGUI_API definitions in v1.92.0 only (https://github.com/ocornut/imgui/pull/8729)
add_patches("v1.92.0", "patches/v1.92.0/fix_imgui_api.patch", "e8ca0502056acf356f83703e7190dda87fde43ed245f65f0fb55b85cd164ed83")
add_patches("v1.92.0-docking", "patches/v1.92.0/fix_imgui_api.patch", "e8ca0502056acf356f83703e7190dda87fde43ed245f65f0fb55b85cd164ed83")
add_configs("dx9", {description = "Enable the dx9 backend", default = false, type = "boolean"})
add_configs("dx10", {description = "Enable the dx10 backend", default = false, type = "boolean"})
add_configs("dx11", {description = "Enable the dx11 backend", default = false, type = "boolean"})
add_configs("dx12", {description = "Enable the dx12 backend", default = false, type = "boolean"})
add_configs("glfw", {description = "Enable the glfw backend", default = false, type = "boolean"})
add_configs("opengl2", {description = "Enable the opengl2 backend", default = false, type = "boolean"})
add_configs("opengl3", {description = "Enable the opengl3 backend", default = false, type = "boolean"})
add_configs("sdl2", {description = "Enable the sdl2 backend with sdl2_renderer", default = false, type = "boolean"})
add_configs("sdl2_no_renderer", {description = "Enable the sdl2 backend without sdl2_renderer", default = false, type = "boolean"})
add_configs("sdl2_renderer", {description = "Enable the sdl2 renderer backend", default = false, type = "boolean"})
add_configs("sdl3", {description = "Enable the sdl3 backend with sdl3_renderer", default = false, type = "boolean"})
add_configs("sdl3_renderer", {description = "Enable the sdl3 renderer backend", default = false, type = "boolean"})
add_configs("sdl3_gpu", {description = "Enable the sdl3 gpu backend", default = false, type = "boolean"})
add_configs("vulkan", {description = "Enable the vulkan backend", default = false, type = "boolean"})
add_configs("win32", {description = "Enable the win32 backend", default = false, type = "boolean"})
add_configs("osx", {description = "Enable the OS X backend", default = false, type = "boolean"})
add_configs("wgpu", {description = "Enable the wgpu backend", default = false, type = "boolean"})
add_configs("freetype", {description = "Use FreeType to build and rasterize the font atlas", default = false, type = "boolean"})
add_configs("user_config", {description = "Use user config (disables test!)", default = nil, type = "string"})
add_configs("wchar32", {description = "Use 32-bit for ImWchar (default is 16-bit)", default = false, type = "boolean"})
-- deprecated configs (kept for backwards compatibility)
add_configs("sdlrenderer", {description = "(deprecated)", default = false, type = "boolean"})
add_configs("glfw_opengl3", {description = "(deprecated)", default = false, type = "boolean"})
add_configs("glfw_vulkan", {description = "(deprecated)", default = false, type = "boolean"})
add_configs("sdl2_opengl3", {description = "(deprecated)", default = false, type = "boolean"})
add_includedirs("include", "include/imgui", "include/backends", "include/misc/cpp")
if is_plat("windows", "mingw") then
add_syslinks("imm32")
end
on_load(function (package)
-- begin: backwards compatibility
if package:config("sdl2") or package:config("sdlrenderer") then
package:config_set("sdl2_renderer", true)
end
if package:config("glfw_opengl3") then
package:config_set("glfw", true)
package:config_set("opengl3", true)
end
if package:config("glfw_vulkan") then
package:config_set("glfw", true)
package:config_set("vulkan", true)
end
if package:config("sdl2_opengl3") then
package:config_set("sdl2", true)
package:config_set("opengl3", true)
end
-- end: backwards compatibility
if package:config("shared") and is_plat("windows", "mingw") then
package:add("defines", "IMGUI_API=__declspec(dllimport)")
end
if package:config("glfw") then
package:add("deps", "glfw")
end
if package:config("opengl3") then
if not package:gitref() and package:version():lt("1.84") then
package:add("deps", "glad")
package:add("defines", "IMGUI_IMPL_OPENGL_LOADER_GLAD")
end
end
if package:config("sdl2_no_renderer") then
package:add("deps", "libsdl2")
end
if package:config("sdl2_renderer") then
package:add("deps", "libsdl2 >=2.0.17")
end
if package:config("sdl3") or package:config("sdl3_renderer") or package:config("sdl3_gpu") then
package:add("deps", "libsdl3")
end
if package:config("vulkan") then
package:add("deps", "vulkan-headers")
end
if package:config("wgpu") then
package:add("deps", "wgpu-native")
end
if package:config("freetype") then
package:add("deps", "freetype")
end
if package:config("osx") then
package:add("frameworks", "Cocoa", "Carbon", "GameController")
end
end)
on_install(function (package)
local configs = {
dx9 = package:config("dx9"),
dx10 = package:config("dx10"),
dx11 = package:config("dx11"),
dx12 = package:config("dx12"),
glfw = package:config("glfw"),
opengl2 = package:config("opengl2"),
opengl3 = package:config("opengl3"),
glad = package:config("opengl3") and (not package:gitref() and package:version():lt("1.84")),
sdl2 = package:config("sdl2") or package:config("sdl2_no_renderer"),
sdl2_renderer = package:config("sdl2_renderer"),
sdl3 = package:config("sdl3"),
sdl3_renderer = package:config("sdl3_renderer"),
sdl3_gpu = package:config("sdl3_gpu"),
vulkan = package:config("vulkan"),
win32 = package:config("win32"),
osx = package:config("osx"),
wgpu = package:config("wgpu"),
freetype = package:config("freetype"),
user_config = package:config("user_config"),
wchar32 = package:config("wchar32")
}
os.cp(path.join(package:scriptdir(), "port", "xmake.lua"), "xmake.lua")
import("package.tools.xmake").install(package, configs)
end)
on_test(function (package)
if package:config("user_config") ~= nil then return end
local includes = {"imgui.h"}
local defines
if package:config("sdl2_renderer") or package:config("sdl2_no_renderer") then
table.insert(includes, "SDL.h")
defines = "SDL_MAIN_HANDLED"
end
assert(package:check_cxxsnippets({test = [[
void test() {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
ImGui::NewFrame();
ImGui::Text("Hello, world!");
ImGui::ShowDemoWindow(NULL);
ImGui::Render();
ImGui::DestroyContext();
}
]]}, {configs = {languages = "c++14", defines = defines}, includes = includes}))
end)

View File

@@ -46,7 +46,7 @@ end
add_packages("spdlog", "imgui")
includes("thirdparty")
includes("submodules")
target("rd_log")
set_kind("object")