mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-17 17:33:21 +08:00
76 lines
2.3 KiB
C++
76 lines
2.3 KiB
C++
/*
|
|
* @Author: DI JUNKUN
|
|
* @Date: 2026-09-04
|
|
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
|
*/
|
|
|
|
#ifndef _SERVER_WINDOW_STATE_H_
|
|
#define _SERVER_WINDOW_STATE_H_
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace crossdesk::server_window_state {
|
|
|
|
// All values use logical desktop coordinates (including negative monitor
|
|
// origins). The bar's anchor is independent of the panel's changing height.
|
|
struct Rect {
|
|
float x, y, width, height;
|
|
};
|
|
|
|
struct EdgeLayout {
|
|
Rect bar;
|
|
Rect panel;
|
|
bool above;
|
|
};
|
|
|
|
inline EdgeLayout PlacePanel(const Rect &screen, float position,
|
|
float bar_width, float panel_height) {
|
|
constexpr float bar_height = 36;
|
|
constexpr float gap = 6;
|
|
constexpr float margin = 8;
|
|
const float travel = std::max(0.0f, screen.height - bar_height - 2 * margin);
|
|
const float top =
|
|
screen.y + margin + travel * std::clamp(position, 0.0f, 1.0f);
|
|
const float above = std::max(0.0f, top - screen.y - margin - gap);
|
|
const float below = std::max(0.0f, screen.y + screen.height - margin - top -
|
|
bar_height - gap);
|
|
const bool opens_above =
|
|
below < panel_height && (above >= panel_height || above > below);
|
|
const float height = std::min(panel_height, opens_above ? above : below);
|
|
const float width = std::min(225.0f, screen.width);
|
|
return {{screen.x + screen.width - bar_width, top, bar_width, bar_height},
|
|
{screen.x + screen.width - width,
|
|
opens_above ? top - gap - height : top + bar_height + gap, width,
|
|
height},
|
|
opens_above};
|
|
}
|
|
|
|
inline bool Contains(const Rect &rect, float x, float y) {
|
|
return x >= rect.x && y >= rect.y && x < rect.x + rect.width &&
|
|
y < rect.y + rect.height;
|
|
}
|
|
|
|
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
|
|
|
|
#endif
|