[fix] fix control bar position when stream window created

This commit is contained in:
dijunkun
2025-04-10 16:46:53 +08:00
parent 193e905b28
commit fcd0488624
8 changed files with 219 additions and 188 deletions

View File

@@ -104,8 +104,8 @@ int Render::ConnectionStatusWindow(
focus_on_input_widget_ = false; focus_on_input_widget_ = false;
} }
ImGui::InputText("##password", remote_password_, ImGui::InputText("##password", props->remote_password_,
IM_ARRAYSIZE(remote_password_), IM_ARRAYSIZE(props->remote_password_),
ImGuiInputTextFlags_CharsNoBlank); ImGuiInputTextFlags_CharsNoBlank);
ImGui::SetWindowFontScale(0.4f); ImGui::SetWindowFontScale(0.4f);
@@ -138,7 +138,7 @@ int Render::ConnectionStatusWindow(
if (ImGui::Button( if (ImGui::Button(
localization::cancel[localization_language_index_].c_str()) || localization::cancel[localization_language_index_].c_str()) ||
ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::IsKeyPressed(ImGuiKey_Escape)) {
memset(remote_password_, 0, sizeof(remote_password_)); memset(props->remote_password_, 0, sizeof(props->remote_password_));
show_connection_status_window_ = false; show_connection_status_window_ = false;
focus_on_input_widget_ = true; focus_on_input_widget_ = true;
} }

View File

@@ -56,12 +56,12 @@ int Render::ShowRecentConnections() {
ImGuiWindowFlags_NoScrollWithMouse); ImGuiWindowFlags_NoScrollWithMouse);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::PopStyleColor(); ImGui::PopStyleColor();
size_t recent_connections_count = recent_connection_textures_.size(); size_t recent_connections_count = recent_connections_.size();
int count = 0; int count = 0;
float button_width = 22; float button_width = 22;
float button_height = 22; float button_height = 22;
for (auto it = recent_connection_textures_.begin(); for (auto it = recent_connections_.begin(); it != recent_connections_.end();
it != recent_connection_textures_.end(); ++it) { ++it) {
sub_containers_pos[it->first] = ImGui::GetCursorPos(); sub_containers_pos[it->first] = ImGui::GetCursorPos();
std::string recent_connection_sub_window_name = std::string recent_connection_sub_window_name =
"RecentConnectionsSubContainer" + it->first; "RecentConnectionsSubContainer" + it->first;
@@ -77,23 +77,23 @@ int Render::ShowRecentConnections() {
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoScrollbar); ImGuiWindowFlags_NoScrollbar);
std::string connection_info = it->first; std::string connection_info = it->first;
std::string remote_id;
std::string password;
std::string host_name;
// remote id length is 9 // remote id length is 9
// password length is 6 // password length is 6
// connection_info -> remote_id + 'Y' + password + host_name // connection_info -> remote_id + 'Y' + password + host_name
// -> remote_id + 'N' + host_name // -> remote_id + 'N' + host_name
if ('Y' == connection_info[9] && connection_info.size() >= 16) { if ('Y' == connection_info[9] && connection_info.size() >= 16) {
remote_id = connection_info.substr(0, 9); it->second.remote_id = connection_info.substr(0, 9);
password = connection_info.substr(10, 6); it->second.password = connection_info.substr(10, 6);
host_name = connection_info.substr(16); it->second.remote_host_name = connection_info.substr(16);
it->second.remember_password = true;
} else if ('N' == connection_info[9] && connection_info.size() >= 10) { } else if ('N' == connection_info[9] && connection_info.size() >= 10) {
remote_id = connection_info.substr(0, 9); it->second.remote_id = connection_info.substr(0, 9);
host_name = connection_info.substr(10); it->second.remote_host_name = connection_info.substr(10);
it->second.password = "";
it->second.remember_password = false;
} else { } else {
host_name = "unknown"; it->second.remote_host_name = "unknown";
} }
ImVec2 image_screen_pos = ImVec2(ImGui::GetCursorScreenPos().x + 5.0f, ImVec2 image_screen_pos = ImVec2(ImGui::GetCursorScreenPos().x + 5.0f,
@@ -101,7 +101,7 @@ int Render::ShowRecentConnections() {
ImVec2 image_pos = ImVec2 image_pos =
ImVec2(ImGui::GetCursorPosX() + 5.0f, ImGui::GetCursorPosY() + 5.0f); ImVec2(ImGui::GetCursorPosX() + 5.0f, ImGui::GetCursorPosY() + 5.0f);
ImGui::SetCursorPos(image_pos); ImGui::SetCursorPos(image_pos);
ImGui::Image((ImTextureID)(intptr_t)it->second, ImGui::Image((ImTextureID)(intptr_t)it->second.texture,
ImVec2((float)recent_connection_image_width_, ImVec2((float)recent_connection_image_width_,
(float)recent_connection_image_height_)); (float)recent_connection_image_height_));
@@ -113,7 +113,7 @@ int Render::ShowRecentConnections() {
ImVec2 dummy_button_pos = ImVec2 dummy_button_pos =
ImVec2(image_pos.x, image_pos.y + recent_connection_image_height_); ImVec2(image_pos.x, image_pos.y + recent_connection_image_height_);
std::string dummy_button_name = "##DummyButton" + remote_id; std::string dummy_button_name = "##DummyButton" + it->second.remote_id;
ImGui::SetCursorPos(dummy_button_pos); ImGui::SetCursorPos(dummy_button_pos);
ImGui::SetWindowFontScale(0.6f); ImGui::SetWindowFontScale(0.6f);
ImGui::Button(dummy_button_name.c_str(), ImGui::Button(dummy_button_name.c_str(),
@@ -123,14 +123,14 @@ int Render::ShowRecentConnections() {
ImGui::SetCursorPos( ImGui::SetCursorPos(
ImVec2(dummy_button_pos.x + 2.0f, dummy_button_pos.y + 1.0f)); ImVec2(dummy_button_pos.x + 2.0f, dummy_button_pos.y + 1.0f));
ImGui::SetWindowFontScale(0.65f); ImGui::SetWindowFontScale(0.65f);
ImGui::Text("%s", remote_id.c_str()); ImGui::Text("%s", it->second.remote_id.c_str());
ImGui::SetWindowFontScale(1.0f); ImGui::SetWindowFontScale(1.0f);
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::SetWindowFontScale(0.5f); ImGui::SetWindowFontScale(0.5f);
ImGui::Text("%s", host_name.c_str()); ImGui::Text("%s", it->second.remote_host_name.c_str());
ImGui::SetWindowFontScale(1.0f); ImGui::SetWindowFontScale(1.0f);
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
@@ -176,15 +176,8 @@ int Render::ShowRecentConnections() {
connect + "##ConnectionTo" + it->first; connect + "##ConnectionTo" + it->first;
if (ImGui::Button(connect_to_this_connection_button_name.c_str(), if (ImGui::Button(connect_to_this_connection_button_name.c_str(),
ImVec2(button_width, button_height))) { ImVec2(button_width, button_height))) {
remote_id_ = remote_id; ConnectTo(it->second.remote_id, it->second.password.c_str(),
it->second.remember_password);
bool remember_password_flag = false;
if (!password.empty() && password.size() == 6) {
remember_password_flag = true;
memcpy(remote_password_, password.c_str(), 6);
}
ConnectTo(remote_id, remote_password_, remember_password_flag);
} }
} }
ImGui::SetWindowFontScale(1.0f); ImGui::SetWindowFontScale(1.0f);

View File

@@ -68,21 +68,44 @@ int Render::RemoteWindow() {
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::SameLine(); ImGui::SameLine();
std::string remote_id = remote_id_display_;
remote_id.erase(remove_if(remote_id.begin(), remote_id.end(),
static_cast<int (*)(int)>(&isspace)),
remote_id.end());
if (ImGui::Button(ICON_FA_ARROW_RIGHT_LONG, ImVec2(55, 38)) || if (ImGui::Button(ICON_FA_ARROW_RIGHT_LONG, ImVec2(55, 38)) ||
enter_pressed) { enter_pressed) {
connect_button_pressed_ = true; connect_button_pressed_ = true;
remote_id_ = remote_id_display_; bool found = false;
remote_id_.erase(remove_if(remote_id_.begin(), remote_id_.end(), for (auto &[id, props] : recent_connections_) {
static_cast<int (*)(int)>(&isspace)), if (id.find(remote_id) != std::string::npos) {
remote_id_.end()); found = true;
ConnectTo(remote_id_, remote_password_, false); if (client_properties_.find(remote_id) !=
client_properties_.end()) {
if (!client_properties_[remote_id]->connection_established_) {
ConnectTo(props.remote_id, props.password.c_str(), false);
} else {
// todo: show warning message
LOG_INFO("Already connected to [{}]", remote_id);
}
} else {
ConnectTo(props.remote_id, props.password.c_str(), false);
}
}
} }
if (client_properties_.find(remote_id_) != client_properties_.end()) { if (!found) {
auto props = client_properties_[remote_id_]; ConnectTo(remote_id, "", false);
}
}
if (need_to_rejoin_) {
need_to_rejoin_ = false;
for (const auto &[_, props] : client_properties_) {
if (props->rejoin_) { if (props->rejoin_) {
ConnectTo(remote_id_, remote_password_, ConnectTo(props->remote_id_, props->remote_password_,
client_properties_[remote_id_]->remember_password_); props->remember_password_);
}
} }
} }
} }
@@ -133,13 +156,14 @@ int Render::ConnectTo(const std::string &remote_id, const char *password,
int ret = -1; int ret = -1;
auto props = client_properties_[remote_id]; auto props = client_properties_[remote_id];
if (!props->connection_established_) { if (!props->connection_established_) {
props->remember_password_ = remember_password;
memcpy(props->remote_password_, password, 6);
ret = JoinConnection(props->peer_, remote_id.c_str(), password); ret = JoinConnection(props->peer_, remote_id.c_str(), password);
if (0 == ret) { if (0 == ret) {
props->rejoin_ = false; props->rejoin_ = false;
props->remember_password_ = remember_password;
memcpy(props->remote_password_, password, 6);
} else { } else {
props->rejoin_ = true; props->rejoin_ = true;
need_to_rejoin_ = true;
} }
} }

View File

@@ -527,6 +527,7 @@ int Render::CreateStreamWindow() {
SDL_PushEvent(&event); SDL_PushEvent(&event);
stream_window_created_ = true; stream_window_created_ = true;
just_created_ = true;
return 0; return 0;
} }
@@ -841,9 +842,9 @@ void Render::HandleRecentConnections() {
if (reload_recent_connections_ && main_renderer_) { if (reload_recent_connections_ && main_renderer_) {
uint32_t now_time = SDL_GetTicks(); uint32_t now_time = SDL_GetTicks();
if (now_time - recent_connection_image_save_time_ >= 50) { if (now_time - recent_connection_image_save_time_ >= 50) {
int ret = thumbnail_->LoadThumbnail( int ret = thumbnail_->LoadThumbnail(main_renderer_, recent_connections_,
main_renderer_, recent_connection_textures_, &recent_connection_image_width_,
&recent_connection_image_width_, &recent_connection_image_height_); &recent_connection_image_height_);
if (!ret) { if (!ret) {
LOG_INFO("Load recent connection thumbnails"); LOG_INFO("Load recent connection thumbnails");
} }
@@ -1029,6 +1030,9 @@ void Render::ProcessSdlEvent() {
} else if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED && } else if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED &&
stream_window_created_ && stream_window_created_ &&
event.window.windowID == SDL_GetWindowID(stream_window_)) { event.window.windowID == SDL_GetWindowID(stream_window_)) {
if (just_created_) {
just_created_ = false;
} else {
for (auto& [_, props] : client_properties_) { for (auto& [_, props] : client_properties_) {
if (!props->reset_control_bar_pos_) { if (!props->reset_control_bar_pos_) {
props->mouse_diff_control_bar_pos_x_ = 0; props->mouse_diff_control_bar_pos_x_ = 0;
@@ -1076,6 +1080,7 @@ void Render::ProcessSdlEvent() {
(int)render_area_width, (int)render_area_height}; (int)render_area_width, (int)render_area_height};
} }
} }
}
} else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED || } else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ||
event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
bool focus_gained = bool focus_gained =

View File

@@ -240,7 +240,7 @@ class Render {
std::unique_ptr<Thumbnail> thumbnail_; std::unique_ptr<Thumbnail> thumbnail_;
// recent connections // recent connections
std::map<std::string, SDL_Texture *> recent_connection_textures_; std::map<std::string, Thumbnail::RecentConnection> recent_connections_;
int recent_connection_image_width_ = 160; int recent_connection_image_width_ = 160;
int recent_connection_image_height_ = 90; int recent_connection_image_height_ = 90;
uint32_t recent_connection_image_save_time_ = 0; uint32_t recent_connection_image_save_time_ = 0;
@@ -296,13 +296,13 @@ class Render {
char input_password_tmp_[7] = ""; char input_password_tmp_[7] = "";
char input_password_[7] = ""; char input_password_[7] = "";
std::string random_password_ = ""; std::string random_password_ = "";
char remote_password_[7] = "";
char new_password_[7] = ""; char new_password_[7] = "";
char remote_id_display_[12] = ""; char remote_id_display_[12] = "";
std::string remote_id_ = "";
unsigned char audio_buffer_[720]; unsigned char audio_buffer_[720];
int audio_len_ = 0; int audio_len_ = 0;
bool audio_buffer_fresh_ = false; bool audio_buffer_fresh_ = false;
bool need_to_rejoin_ = false;
bool just_created_ = false;
// stream window render // stream window render
SDL_Window *stream_window_ = nullptr; SDL_Window *stream_window_ = nullptr;

View File

@@ -359,9 +359,7 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char *user_id,
render->StopSpeakerCapturer(); render->StopSpeakerCapturer();
render->audio_capture_ = false; render->audio_capture_ = false;
} }
if (!render->rejoin_) {
memset(render->remote_password_, 0, sizeof(render->remote_password_));
}
if (props->dst_buffer_) { if (props->dst_buffer_) {
memset(props->dst_buffer_, 0, props->dst_buffer_capacity_); memset(props->dst_buffer_, 0, props->dst_buffer_capacity_);
SDL_UpdateTexture(props->stream_texture_, NULL, props->dst_buffer_, SDL_UpdateTexture(props->stream_texture_, NULL, props->dst_buffer_,

View File

@@ -23,6 +23,65 @@
static std::string test; static std::string test;
bool LoadTextureFromMemory(const void* data, size_t data_size,
SDL_Renderer* renderer, SDL_Texture** out_texture,
int* out_width, int* out_height) {
int image_width = 0;
int image_height = 0;
int channels = 4;
unsigned char* image_data =
stbi_load_from_memory((const unsigned char*)data, (int)data_size,
&image_width, &image_height, NULL, 4);
if (image_data == nullptr) {
LOG_ERROR("Failed to load image: [{}]", stbi_failure_reason());
return false;
}
// ABGR
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(
(void*)image_data, image_width, image_height, channels * 8,
channels * image_width, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
if (surface == nullptr) {
LOG_ERROR("Failed to create SDL surface: [{}]", SDL_GetError());
return false;
}
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (texture == nullptr) {
LOG_ERROR("Failed to create SDL texture: [{}]", SDL_GetError());
}
*out_texture = texture;
*out_width = image_width;
*out_height = image_height;
SDL_FreeSurface(surface);
stbi_image_free(image_data);
return true;
}
bool LoadTextureFromFile(const char* file_name, SDL_Renderer* renderer,
SDL_Texture** out_texture, int* out_width,
int* out_height) {
std::filesystem::path file_path(file_name);
if (!std::filesystem::exists(file_path)) return false;
std::ifstream file(file_path, std::ios::binary);
if (!file) return false;
file.seekg(0, std::ios::end);
size_t file_size = file.tellg();
file.seekg(0, std::ios::beg);
if (file_size == -1) return false;
char* file_data = new char[file_size];
if (!file_data) return false;
file.read(file_data, file_size);
bool ret = LoadTextureFromMemory(file_data, file_size, renderer, out_texture,
out_width, out_height);
delete[] file_data;
return ret;
}
void ScaleYUV420pToABGR(char* dst_buffer_, int video_width_, int video_height_, void ScaleYUV420pToABGR(char* dst_buffer_, int video_width_, int video_height_,
int scaled_video_width_, int scaled_video_height_, int scaled_video_width_, int scaled_video_height_,
char* rgba_buffer_) { char* rgba_buffer_) {
@@ -87,7 +146,7 @@ int Thumbnail::SaveToThumbnail(const char* yuv420p, int width, int height,
std::string image_name; std::string image_name;
if (password.empty()) { if (password.empty()) {
image_name = remote_id + 'N' + host_name; return 0;
} else { } else {
// delete the file which has no password in its name // delete the file which has no password in its name
std::string filename_without_password = remote_id + "N" + host_name; std::string filename_without_password = remote_id + "N" + host_name;
@@ -104,63 +163,49 @@ int Thumbnail::SaveToThumbnail(const char* yuv420p, int width, int height,
return 0; return 0;
} }
bool LoadTextureFromMemory(const void* data, size_t data_size, int Thumbnail::LoadThumbnail(
SDL_Renderer* renderer, SDL_Texture** out_texture, SDL_Renderer* renderer,
int* out_width, int* out_height) { std::map<std::string, RecentConnection>& recent_connections, int* width,
int image_width = 0; int* height) {
int image_height = 0; for (auto& it : recent_connections) {
int channels = 4; if (it.second.texture != nullptr) {
unsigned char* image_data = SDL_DestroyTexture(it.second.texture);
stbi_load_from_memory((const unsigned char*)data, (int)data_size, it.second.texture = nullptr;
&image_width, &image_height, NULL, 4); }
if (image_data == nullptr) { }
LOG_ERROR("Failed to load image: [{}]", stbi_failure_reason()); recent_connections.clear();
return false;
std::vector<std::filesystem::path> image_paths =
FindThumbnailPath(image_path_);
if (image_paths.size() == 0) {
return -1;
} else {
for (int i = 0; i < image_paths.size(); i++) {
size_t pos1 = image_paths[i].string().find('/') + 1;
std::string cipher_image_name = image_paths[i].string().substr(pos1);
std::string original_image_name =
AES_decrypt(cipher_image_name, aes128_key_, aes128_iv_);
std::string image_path = image_path_ + cipher_image_name;
recent_connections[original_image_name].texture = nullptr;
LoadTextureFromFile(image_path.c_str(), renderer,
&(recent_connections[original_image_name].texture),
width, height);
}
return 0;
}
return 0;
} }
// ABGR int Thumbnail::DeleteThumbnail(const std::string& file_name) {
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom( std::string ciphertext = AES_encrypt(file_name, aes128_key_, aes128_iv_);
(void*)image_data, image_width, image_height, channels * 8, std::string file_path = image_path_ + ciphertext;
channels * image_width, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); if (std::filesystem::exists(file_path)) {
if (surface == nullptr) { std::filesystem::remove(file_path);
LOG_ERROR("Failed to create SDL surface: [{}]", SDL_GetError()); return 0;
return false; } else {
return -1;
} }
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (texture == nullptr) {
LOG_ERROR("Failed to create SDL texture: [{}]", SDL_GetError());
}
*out_texture = texture;
*out_width = image_width;
*out_height = image_height;
SDL_FreeSurface(surface);
stbi_image_free(image_data);
return true;
}
bool LoadTextureFromFile(const char* file_name, SDL_Renderer* renderer,
SDL_Texture** out_texture, int* out_width,
int* out_height) {
std::filesystem::path file_path(file_name);
if (!std::filesystem::exists(file_path)) return false;
std::ifstream file(file_path, std::ios::binary);
if (!file) return false;
file.seekg(0, std::ios::end);
size_t file_size = file.tellg();
file.seekg(0, std::ios::beg);
if (file_size == -1) return false;
char* file_data = new char[file_size];
if (!file_data) return false;
file.read(file_data, file_size);
bool ret = LoadTextureFromMemory(file_data, file_size, renderer, out_texture,
out_width, out_height);
delete[] file_data;
return ret;
} }
std::vector<std::filesystem::path> Thumbnail::FindThumbnailPath( std::vector<std::filesystem::path> Thumbnail::FindThumbnailPath(
@@ -194,49 +239,6 @@ std::vector<std::filesystem::path> Thumbnail::FindThumbnailPath(
return thumbnails_path; return thumbnails_path;
} }
int Thumbnail::LoadThumbnail(SDL_Renderer* renderer,
std::map<std::string, SDL_Texture*>& textures,
int* width, int* height) {
for (auto& it : textures) {
if (it.second != nullptr) {
SDL_DestroyTexture(it.second);
it.second = nullptr;
}
}
textures.clear();
std::vector<std::filesystem::path> image_paths =
FindThumbnailPath(image_path_);
if (image_paths.size() == 0) {
return -1;
} else {
for (int i = 0; i < image_paths.size(); i++) {
size_t pos1 = image_paths[i].string().find('/') + 1;
std::string cipher_image_name = image_paths[i].string().substr(pos1);
std::string original_image_name =
AES_decrypt(cipher_image_name, aes128_key_, aes128_iv_);
std::string image_path = image_path_ + cipher_image_name;
textures[original_image_name] = nullptr;
LoadTextureFromFile(image_path.c_str(), renderer,
&(textures[original_image_name]), width, height);
}
return 0;
}
return 0;
}
int Thumbnail::DeleteThumbnail(const std::string& file_name) {
std::string ciphertext = AES_encrypt(file_name, aes128_key_, aes128_iv_);
std::string file_path = image_path_ + ciphertext;
if (std::filesystem::exists(file_path)) {
std::filesystem::remove(file_path);
return 0;
} else {
return -1;
}
}
int Thumbnail::DeleteAllFilesInDirectory() { int Thumbnail::DeleteAllFilesInDirectory() {
if (std::filesystem::exists(image_path_) && if (std::filesystem::exists(image_path_) &&
std::filesystem::is_directory(image_path_)) { std::filesystem::is_directory(image_path_)) {

View File

@@ -13,6 +13,15 @@
#include <map> #include <map>
class Thumbnail { class Thumbnail {
public:
struct RecentConnection {
SDL_Texture* texture = nullptr;
std::string remote_id;
std::string remote_host_name;
std::string password;
bool remember_password = false;
};
public: public:
Thumbnail(); Thumbnail();
explicit Thumbnail(unsigned char* aes128_key, unsigned char* aes128_iv); explicit Thumbnail(unsigned char* aes128_key, unsigned char* aes128_iv);
@@ -25,8 +34,8 @@ class Thumbnail {
const std::string& password); const std::string& password);
int LoadThumbnail(SDL_Renderer* renderer, int LoadThumbnail(SDL_Renderer* renderer,
std::map<std::string, SDL_Texture*>& textures, int* width, std::map<std::string, RecentConnection>& recent_connections,
int* height); int* width, int* height);
int DeleteThumbnail(const std::string& file_name); int DeleteThumbnail(const std::string& file_name);