mirror of
https://github.com/hyprwm/hyprlock.git
synced 2025-02-03 16:29:48 +01:00
widgets: extend shell cmd exec to Label
This commit is contained in:
parent
02639c2759
commit
a0a59aeef2
4 changed files with 135 additions and 4 deletions
|
@ -30,11 +30,92 @@ class CLayoutValueData : public ICustomConfigValueData {
|
|||
CLayoutValueData() {};
|
||||
virtual ~CLayoutValueData() {};
|
||||
|
||||
struct SExecuteResult {
|
||||
Hyprutils::Math::Vector2D values;
|
||||
struct {
|
||||
bool x = false;
|
||||
bool y = false;
|
||||
} isRelative;
|
||||
};
|
||||
|
||||
SExecuteResult executeCommand() {
|
||||
if (!m_bIsCommand)
|
||||
return {{0,0}, {false, false}};
|
||||
|
||||
FILE* pipe = popen(m_sCommand.c_str(), "r");
|
||||
if (!pipe) {
|
||||
Debug::log(ERR, "Failed to execute position command");
|
||||
return {{0,0}, {false, false}};
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
std::string result = "";
|
||||
while (!feof(pipe)) {
|
||||
if (fgets(buffer, 128, pipe) != NULL)
|
||||
result += buffer;
|
||||
}
|
||||
pclose(pipe);
|
||||
|
||||
if (!result.empty() && result.back() == '\n')
|
||||
result.pop_back();
|
||||
|
||||
SExecuteResult out;
|
||||
const auto SPLIT = result.find(',');
|
||||
if (SPLIT == std::string::npos) {
|
||||
Debug::log(ERR, "Position command output must be x,y format");
|
||||
return {{0,0}, {false, false}};
|
||||
}
|
||||
|
||||
auto lhs = result.substr(0, SPLIT);
|
||||
auto rhs = result.substr(SPLIT + 1);
|
||||
if (rhs.starts_with(" "))
|
||||
rhs = rhs.substr(1);
|
||||
|
||||
if (lhs.ends_with("%")) {
|
||||
out.isRelative.x = true;
|
||||
lhs.pop_back();
|
||||
}
|
||||
|
||||
if (rhs.ends_with("%")) {
|
||||
out.isRelative.y = true;
|
||||
rhs.pop_back();
|
||||
}
|
||||
|
||||
try {
|
||||
out.values = {std::stof(lhs), std::stof(rhs)};
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Failed to parse command output as coordinates");
|
||||
return {{0,0}, {false, false}};
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool needsUpdate() const {
|
||||
return m_bIsCommand;
|
||||
}
|
||||
|
||||
float updateMs() const {
|
||||
return m_bIsCommand ? m_iUpdateMs : 0;
|
||||
}
|
||||
|
||||
void update() {
|
||||
if (!m_bIsCommand)
|
||||
return;
|
||||
|
||||
auto result = executeCommand();
|
||||
m_vValues = result.values;
|
||||
m_sIsRelative.x = result.isRelative.x;
|
||||
m_sIsRelative.y = result.isRelative.y;
|
||||
}
|
||||
|
||||
virtual eConfigValueDataTypes getDataType() {
|
||||
return CVD_TYPE_LAYOUT;
|
||||
}
|
||||
|
||||
virtual std::string toString() {
|
||||
if (m_bIsCommand)
|
||||
return std::format("cmd[update:{}]{}", m_iUpdateMs, m_sCommand);
|
||||
return std::format("{}{},{}{}", m_vValues.x, (m_sIsRelative.x) ? "%" : "px", m_vValues.y, (m_sIsRelative.y) ? "%" : "px");
|
||||
}
|
||||
|
||||
|
@ -46,6 +127,8 @@ class CLayoutValueData : public ICustomConfigValueData {
|
|||
}
|
||||
|
||||
Hyprutils::Math::Vector2D getAbsolute(const Hyprutils::Math::Vector2D& viewport) {
|
||||
if (m_bIsCommand)
|
||||
update();
|
||||
return {
|
||||
(m_sIsRelative.x ? (m_vValues.x / 100) * viewport.x : m_vValues.x),
|
||||
(m_sIsRelative.y ? (m_vValues.y / 100) * viewport.y : m_vValues.y),
|
||||
|
@ -57,6 +140,10 @@ class CLayoutValueData : public ICustomConfigValueData {
|
|||
bool x = false;
|
||||
bool y = false;
|
||||
} m_sIsRelative;
|
||||
|
||||
bool m_bIsCommand = false;
|
||||
std::string m_sCommand = "";
|
||||
int m_iUpdateMs = 0;
|
||||
};
|
||||
|
||||
class CGradientValueData : public ICustomConfigValueData {
|
||||
|
|
|
@ -63,7 +63,36 @@ static Hyprlang::CParseResult configHandleLayoutOption(const char* v, void** dat
|
|||
if (!*data)
|
||||
*data = new CLayoutValueData();
|
||||
|
||||
const auto DATA = (CLayoutValueData*)(*data);
|
||||
const auto DATA = (CLayoutValueData*)(*data);
|
||||
|
||||
if (VALUE.starts_with("cmd[") && VALUE.contains("]")) {
|
||||
DATA->m_bIsCommand = true;
|
||||
|
||||
std::string options = VALUE.substr(4, VALUE.find_first_of(']') - 4);
|
||||
CVarList vars(options, 0, ',', true);
|
||||
|
||||
for (const auto& var : vars) {
|
||||
if (var.starts_with("update:")) {
|
||||
try {
|
||||
DATA->m_iUpdateMs = std::stoull(var.substr(7));
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Error parsing {} in cmd[]", var);
|
||||
}
|
||||
} else {
|
||||
Debug::log(ERR, "Unknown prop in layout format {}", var);
|
||||
}
|
||||
}
|
||||
|
||||
DATA->m_sCommand = VALUE.substr(VALUE.find_first_of(']') + 1);
|
||||
|
||||
auto cmdResult = DATA->executeCommand();
|
||||
DATA->m_vValues = cmdResult.values;
|
||||
DATA->m_sIsRelative.x = cmdResult.isRelative.x;
|
||||
DATA->m_sIsRelative.y = cmdResult.isRelative.y;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto SPLIT = VALUE.find(',');
|
||||
if (SPLIT == std::string::npos) {
|
||||
result.setError(std::format("expected two comma seperated values, got {}", VALUE).c_str());
|
||||
|
|
|
@ -44,6 +44,18 @@ void CLabel::onTimerUpdate() {
|
|||
|
||||
label = formatString(labelPreFormat);
|
||||
|
||||
try {
|
||||
const auto LAYOUT = CLayoutValueData::fromAnyPv(props.at("position"));
|
||||
if (LAYOUT->needsUpdate()) {
|
||||
const auto OLD_POS = LAYOUT->getAbsolute(viewport);
|
||||
LAYOUT->update();
|
||||
if (OLD_POS != LAYOUT->getAbsolute(viewport)) { // redraw:
|
||||
configPos = LAYOUT->getAbsolute(viewport);
|
||||
g_pHyprlock->renderOutput(outputStringPort);
|
||||
}
|
||||
}
|
||||
} catch (...) { /* TODO */ }
|
||||
|
||||
if (label.formatted == oldFormatted && !label.alwaysUpdate)
|
||||
return;
|
||||
|
||||
|
@ -70,8 +82,8 @@ void CLabel::plantTimer() {
|
|||
labelTimer = g_pHyprlock->addTimer(std::chrono::hours(1), onTimer, this, true);
|
||||
}
|
||||
|
||||
CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string, std::any>& props, const std::string& output) :
|
||||
outputStringPort(output), shadow(this, props, viewport_) {
|
||||
CLabel::CLabel(const Vector2D& viewport_, const WidgetProps& props_, const std::string& output) :
|
||||
outputStringPort(output), shadow(this, props_, viewport_), props(props_) {
|
||||
try {
|
||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
|
||||
labelPreFormat = std::any_cast<Hyprlang::STRING>(props.at("text"));
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
struct SPreloadedAsset;
|
||||
class CSessionLockSurface;
|
||||
|
||||
using WidgetProps = std::unordered_map<std::string, std::any>;
|
||||
|
||||
class CLabel : public IWidget {
|
||||
public:
|
||||
CLabel(const Vector2D& viewport, const std::unordered_map<std::string, std::any>& props, const std::string& output);
|
||||
CLabel(const Vector2D& viewport_, const WidgetProps& props_, const std::string& output);
|
||||
~CLabel();
|
||||
|
||||
virtual bool draw(const SRenderData& data);
|
||||
|
@ -46,4 +48,5 @@ class CLabel : public IWidget {
|
|||
|
||||
CShadowable shadow;
|
||||
bool updateShadow = true;
|
||||
WidgetProps props;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue