mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-08-26 13:29:31 +08:00
[fix] correct controlled-side status window behavior
This commit is contained in:
@@ -50,8 +50,10 @@
|
|||||||
#include "platform/tray/linux_tray.h"
|
#include "platform/tray/linux_tray.h"
|
||||||
#endif
|
#endif
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
#include "server_window_state.h"
|
||||||
#include "ui/ui_localization.h"
|
#include "ui/ui_localization.h"
|
||||||
#include "version_checker.h"
|
#include "version_checker.h"
|
||||||
|
#include "window_geometry.h"
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -692,18 +694,43 @@ float StreamWindowLogicalHeight(bool custom_titlebar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayID DisplayForSlintWindow(const slint::Window& window) {
|
SDL_DisplayID DisplayForSlintWindow(const slint::Window& window) {
|
||||||
const float scale = std::max(window.scale_factor(), 0.01f);
|
|
||||||
const auto position = window.position();
|
const auto position = window.position();
|
||||||
const auto size = window.size();
|
const auto size = window.size();
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
const float scale = std::max(window.scale_factor(), 0.01f);
|
||||||
const SDL_Point center{
|
const SDL_Point center{
|
||||||
static_cast<int>(
|
static_cast<int>(
|
||||||
std::lround(position.x / scale + size.width / (2.0f * scale))),
|
std::lround(position.x / scale + size.width / (2.0f * scale))),
|
||||||
static_cast<int>(
|
static_cast<int>(
|
||||||
std::lround(position.y / scale + size.height / (2.0f * scale)))};
|
std::lround(position.y / scale + size.height / (2.0f * scale)))};
|
||||||
|
#else
|
||||||
|
const SDL_Point center{
|
||||||
|
position.x + static_cast<int>(size.width / 2),
|
||||||
|
position.y + static_cast<int>(size.height / 2)};
|
||||||
|
#endif
|
||||||
const SDL_DisplayID display = SDL_GetDisplayForPoint(¢er);
|
const SDL_DisplayID display = SDL_GetDisplayForPoint(¢er);
|
||||||
return display != 0 ? display : SDL_GetPrimaryDisplay();
|
return display != 0 ? display : SDL_GetPrimaryDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
window_geometry::PhysicalSize PhysicalWindowSize(const slint::Window& window,
|
||||||
|
float logical_width,
|
||||||
|
float logical_height) {
|
||||||
|
const auto size = window.size();
|
||||||
|
if (size.width > 0 && size.height > 0) {
|
||||||
|
return {static_cast<int>(size.width), static_cast<int>(size.height)};
|
||||||
|
}
|
||||||
|
|
||||||
|
const float scale = std::max(window.scale_factor(), 0.01f);
|
||||||
|
return {std::max(1, static_cast<int>(std::lround(logical_width * scale))),
|
||||||
|
std::max(1, static_cast<int>(std::lround(logical_height * scale)))};
|
||||||
|
}
|
||||||
|
|
||||||
|
window_geometry::PhysicalRect PhysicalDisplayBounds(const SDL_Rect& bounds) {
|
||||||
|
return {bounds.x, bounds.y, bounds.w, bounds.h};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool PositionWindowAtCenter(slint::Window& window, const slint::Window& anchor,
|
bool PositionWindowAtCenter(slint::Window& window, const slint::Window& anchor,
|
||||||
float logical_width, float logical_height) {
|
float logical_width, float logical_height) {
|
||||||
if (!CanUseGlobalPointerPosition()) {
|
if (!CanUseGlobalPointerPosition()) {
|
||||||
@@ -718,6 +745,7 @@ bool PositionWindowAtCenter(slint::Window& window, const slint::Window& anchor,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
const float target_x =
|
const float target_x =
|
||||||
static_cast<float>(usable_bounds.x) +
|
static_cast<float>(usable_bounds.x) +
|
||||||
(static_cast<float>(usable_bounds.w) - logical_width) / 2.0f;
|
(static_cast<float>(usable_bounds.w) - logical_width) / 2.0f;
|
||||||
@@ -726,6 +754,13 @@ bool PositionWindowAtCenter(slint::Window& window, const slint::Window& anchor,
|
|||||||
(static_cast<float>(usable_bounds.h) - logical_height) / 2.0f;
|
(static_cast<float>(usable_bounds.h) - logical_height) / 2.0f;
|
||||||
window.set_position(
|
window.set_position(
|
||||||
slint::LogicalPosition(slint::Point<float>{target_x, target_y}));
|
slint::LogicalPosition(slint::Point<float>{target_x, target_y}));
|
||||||
|
#else
|
||||||
|
const auto target = window_geometry::CenteredPosition(
|
||||||
|
PhysicalDisplayBounds(usable_bounds),
|
||||||
|
PhysicalWindowSize(window, logical_width, logical_height));
|
||||||
|
window.set_position(slint::PhysicalPosition(
|
||||||
|
slint::Point<int32_t>{target.x, target.y}));
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,16 +770,21 @@ bool PositionWindowAtBottomRight(slint::Window& window, float logical_width,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayID display = 0;
|
|
||||||
const float scale = std::max(window.scale_factor(), 0.01f);
|
|
||||||
const auto position = window.position();
|
const auto position = window.position();
|
||||||
const auto size = window.size();
|
const auto size = window.size();
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
const float scale = std::max(window.scale_factor(), 0.01f);
|
||||||
const SDL_Point center{
|
const SDL_Point center{
|
||||||
static_cast<int>(
|
static_cast<int>(
|
||||||
std::lround(position.x / scale + size.width / (2.0f * scale))),
|
std::lround(position.x / scale + size.width / (2.0f * scale))),
|
||||||
static_cast<int>(
|
static_cast<int>(
|
||||||
std::lround(position.y / scale + size.height / (2.0f * scale)))};
|
std::lround(position.y / scale + size.height / (2.0f * scale)))};
|
||||||
display = SDL_GetDisplayForPoint(¢er);
|
#else
|
||||||
|
const SDL_Point center{
|
||||||
|
position.x + static_cast<int>(size.width / 2),
|
||||||
|
position.y + static_cast<int>(size.height / 2)};
|
||||||
|
#endif
|
||||||
|
SDL_DisplayID display = SDL_GetDisplayForPoint(¢er);
|
||||||
if (display == 0) {
|
if (display == 0) {
|
||||||
display = SDL_GetPrimaryDisplay();
|
display = SDL_GetPrimaryDisplay();
|
||||||
}
|
}
|
||||||
@@ -756,6 +796,7 @@ bool PositionWindowAtBottomRight(slint::Window& window, float logical_width,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
const float target_x =
|
const float target_x =
|
||||||
static_cast<float>(usable_bounds.x) +
|
static_cast<float>(usable_bounds.x) +
|
||||||
std::max(0.0f, static_cast<float>(usable_bounds.w) - logical_width);
|
std::max(0.0f, static_cast<float>(usable_bounds.w) - logical_width);
|
||||||
@@ -764,9 +805,33 @@ bool PositionWindowAtBottomRight(slint::Window& window, float logical_width,
|
|||||||
std::max(0.0f, static_cast<float>(usable_bounds.h) - logical_height);
|
std::max(0.0f, static_cast<float>(usable_bounds.h) - logical_height);
|
||||||
window.set_position(
|
window.set_position(
|
||||||
slint::LogicalPosition(slint::Point<float>{target_x, target_y}));
|
slint::LogicalPosition(slint::Point<float>{target_x, target_y}));
|
||||||
|
#else
|
||||||
|
const auto target = window_geometry::BottomRightPosition(
|
||||||
|
PhysicalDisplayBounds(usable_bounds),
|
||||||
|
PhysicalWindowSize(window, logical_width, logical_height));
|
||||||
|
window.set_position(slint::PhysicalPosition(
|
||||||
|
slint::Point<int32_t>{target.x, target.y}));
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
bool ConfigureWindowsServerWindow(slint::Window& window) {
|
||||||
|
const HWND hwnd = window.win32_hwnd();
|
||||||
|
if (!hwnd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG_PTR ex_style = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
|
||||||
|
ex_style |= WS_EX_TOOLWINDOW;
|
||||||
|
ex_style &= ~WS_EX_APPWINDOW;
|
||||||
|
SetWindowLongPtr(hwnd, GWL_EXSTYLE, ex_style);
|
||||||
|
return SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
||||||
|
SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED |
|
||||||
|
SWP_NOACTIVATE) != FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename WindowHandle>
|
template <typename WindowHandle>
|
||||||
void DragWindow(WindowHandle& component, int phase, float mouse_x,
|
void DragWindow(WindowHandle& component, int phase, float mouse_x,
|
||||||
float mouse_y, WindowDragState& state) {
|
float mouse_y, WindowDragState& state) {
|
||||||
@@ -897,6 +962,9 @@ struct GuiApplication::SlintUi {
|
|||||||
#endif
|
#endif
|
||||||
int stream_initial_position_attempts = 0;
|
int stream_initial_position_attempts = 0;
|
||||||
int server_initial_position_attempts = 0;
|
int server_initial_position_attempts = 0;
|
||||||
|
#if _WIN32
|
||||||
|
int server_native_window_attempts = 0;
|
||||||
|
#endif
|
||||||
int localized_language = -1;
|
int localized_language = -1;
|
||||||
std::chrono::steady_clock::time_point last_clipboard_poll{};
|
std::chrono::steady_clock::time_point last_clipboard_poll{};
|
||||||
slint::Timer video_timer;
|
slint::Timer video_timer;
|
||||||
@@ -3024,6 +3092,9 @@ void GuiApplication::SyncServerWindow() {
|
|||||||
// the right and bottom edges correct when the backend resolves DPI and
|
// the right and bottom edges correct when the backend resolves DPI and
|
||||||
// language-dependent preferred width asynchronously on first show.
|
// language-dependent preferred width asynchronously on first show.
|
||||||
ui_->server_initial_position_attempts = 2;
|
ui_->server_initial_position_attempts = 2;
|
||||||
|
#if _WIN32
|
||||||
|
ui_->server_native_window_attempts = 30;
|
||||||
|
#endif
|
||||||
server_window_created_ = true;
|
server_window_created_ = true;
|
||||||
server_window_inited_ = true;
|
server_window_inited_ = true;
|
||||||
}
|
}
|
||||||
@@ -3033,6 +3104,9 @@ void GuiApplication::SyncServerWindow() {
|
|||||||
server_window_created_ = false;
|
server_window_created_ = false;
|
||||||
server_window_inited_ = false;
|
server_window_inited_ = false;
|
||||||
ui_->server_initial_position_attempts = 0;
|
ui_->server_initial_position_attempts = 0;
|
||||||
|
#if _WIN32
|
||||||
|
ui_->server_native_window_attempts = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (!ui_->server) {
|
if (!ui_->server) {
|
||||||
return;
|
return;
|
||||||
@@ -3060,18 +3134,19 @@ void GuiApplication::SyncServerWindow() {
|
|||||||
}
|
}
|
||||||
ui_->controller_model->set_vector(std::move(controllers));
|
ui_->controller_model->set_vector(std::move(controllers));
|
||||||
ui_->controller_name_model->set_vector(std::move(names));
|
ui_->controller_name_model->set_vector(std::move(names));
|
||||||
if (selected_server_remote_id_.empty() && !ui_->controller_ids.empty()) {
|
const int selected = server_window_state::ReconcileSelectedController(
|
||||||
selected_server_remote_id_ = ui_->controller_ids.front();
|
ui_->controller_ids, &selected_server_remote_id_);
|
||||||
}
|
|
||||||
int selected = 0;
|
|
||||||
for (int i = 0; i < static_cast<int>(ui_->controller_ids.size()); ++i) {
|
|
||||||
if (ui_->controller_ids[i] == selected_server_remote_id_) {
|
|
||||||
selected = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*ui_->server)->set_selected_controller(selected);
|
(*ui_->server)->set_selected_controller(selected);
|
||||||
(*ui_->server)->set_language_index(localization_language_index_);
|
(*ui_->server)->set_language_index(localization_language_index_);
|
||||||
|
#if _WIN32
|
||||||
|
if (ui_->server_native_window_attempts > 0) {
|
||||||
|
if (ConfigureWindowsServerWindow((*ui_->server)->window())) {
|
||||||
|
ui_->server_native_window_attempts = 0;
|
||||||
|
} else {
|
||||||
|
--ui_->server_native_window_attempts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (ui_->server_initial_position_attempts > 0) {
|
if (ui_->server_initial_position_attempts > 0) {
|
||||||
const float server_width =
|
const float server_width =
|
||||||
ServerWindowLogicalWidth(localization_language_index_);
|
ServerWindowLogicalWidth(localization_language_index_);
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace crossdesk::server_window_state {
|
||||||
|
|
||||||
|
inline int ReconcileSelectedController(const std::vector<std::string>& ids,
|
||||||
|
std::string* selected_id) {
|
||||||
|
if (!selected_id) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ids.empty()) {
|
||||||
|
selected_id->clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto selected = std::find(ids.begin(), ids.end(), *selected_id);
|
||||||
|
if (selected == ids.end()) {
|
||||||
|
*selected_id = ids.front();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<int>(std::distance(ids.begin(), selected));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crossdesk::server_window_state
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace crossdesk::window_geometry {
|
||||||
|
|
||||||
|
struct PhysicalRect {
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhysicalSize {
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhysicalPosition {
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr PhysicalPosition CenteredPosition(const PhysicalRect& bounds,
|
||||||
|
const PhysicalSize& size) {
|
||||||
|
return {
|
||||||
|
bounds.x + (bounds.width - std::min(bounds.width, size.width)) / 2,
|
||||||
|
bounds.y + (bounds.height - std::min(bounds.height, size.height)) / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr PhysicalPosition BottomRightPosition(const PhysicalRect& bounds,
|
||||||
|
const PhysicalSize& size) {
|
||||||
|
return {
|
||||||
|
bounds.x + std::max(0, bounds.width - size.width),
|
||||||
|
bounds.y + std::max(0, bounds.height - size.height),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crossdesk::window_geometry
|
||||||
Reference in New Issue
Block a user