Skip to content

Commit

Permalink
label: add executing commands
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Feb 21, 2024
1 parent 3d27060 commit 5370762
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 4 deletions.
70 changes: 70 additions & 0 deletions src/core/hyprlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,3 +539,73 @@ std::shared_ptr<CTimer> CHyprlock::addTimer(const std::chrono::system_clock::dur
m_sLoopState.timerCV.notify_all();
return T;
}

void CHyprlock::spawnAsync(const std::string& args) {
Debug::log(LOG, "Executing (async) {}", args);

int socket[2];
if (pipe(socket) != 0)
Debug::log(LOG, "Unable to create pipe for fork");

pid_t child, grandchild;
child = fork();

if (child < 0) {
close(socket[0]);
close(socket[1]);
Debug::log(LOG, "Fail to create the first fork");
return;
}

if (child == 0) {
// run in child

sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);

grandchild = fork();

if (grandchild == 0) {
// run in grandchild
close(socket[0]);
close(socket[1]);
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
// exit grandchild
_exit(0);
}

close(socket[0]);
write(socket[1], &grandchild, sizeof(grandchild));
close(socket[1]);
// exit child
_exit(0);
}

// run in parent
close(socket[1]);
read(socket[0], &grandchild, sizeof(grandchild));
close(socket[0]);
// clear child and leave child to init
waitpid(child, NULL, 0);

if (child < 0) {
Debug::log(LOG, "Failed to create the second fork");
return;
}

Debug::log(LOG, "Process Created with pid {}", grandchild);
}

std::string CHyprlock::spawnSync(const std::string& cmd) {
std::array<char, 128> buffer;
std::string result;
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
if (!pipe)
return "";

while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
3 changes: 3 additions & 0 deletions src/core/hyprlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class CHyprlock {
void lockSession();
void unlockSession();

void spawnAsync(const std::string& cmd);
std::string spawnSync(const std::string& cmd);

void onKey(uint32_t key);
void onPasswordCheckTimer();
bool passwordCheckWaiting();
Expand Down
8 changes: 5 additions & 3 deletions src/renderer/AsyncResourceGatherer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ void CAsyncResourceGatherer::renderText(const SPreloadRequest& rq) {
const int FONTSIZE = rq.props.contains("font_size") ? std::any_cast<int>(rq.props.at("font_size")) : 16;
const CColor FONTCOLOR = rq.props.contains("color") ? std::any_cast<CColor>(rq.props.at("color")) : CColor(1.0, 1.0, 1.0, 1.0);
const std::string FONTFAMILY = rq.props.contains("font_family") ? std::any_cast<std::string>(rq.props.at("font_family")) : "Sans";
const bool ISCMD = rq.props.contains("cmd") ? std::any_cast<bool>(rq.props.at("cmd")) : false;
const std::string TEXT = ISCMD ? g_pHyprlock->spawnSync(rq.asset) : rq.asset;

auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1920, 1080 /* dummy value */);
auto CAIRO = cairo_create(CAIROSURFACE);
Expand All @@ -144,12 +146,12 @@ void CAsyncResourceGatherer::renderText(const SPreloadRequest& rq) {
PangoAttrList* attrList = nullptr;
GError* gError = nullptr;
char* buf = nullptr;
if (pango_parse_markup(rq.asset.c_str(), -1, 0, &attrList, &buf, nullptr, &gError))
if (pango_parse_markup(TEXT.c_str(), -1, 0, &attrList, &buf, nullptr, &gError))
pango_layout_set_text(layout, buf, -1);
else {
Debug::log(ERR, "Pango markup parsing for {} failed: {}", rq.asset, gError->message);
Debug::log(ERR, "Pango markup parsing for {} failed: {}", TEXT, gError->message);
g_error_free(gError);
pango_layout_set_text(layout, rq.asset.c_str(), -1);
pango_layout_set_text(layout, TEXT.c_str(), -1);
}

if (!attrList)
Expand Down
20 changes: 20 additions & 0 deletions src/renderer/widgets/IWidget.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "IWidget.hpp"
#include "../../helpers/Log.hpp"
#include "../../helpers/VarList.hpp"
#include <chrono>

Vector2D IWidget::posFromHVAlign(const Vector2D& viewport, const Vector2D& size, const Vector2D& offset, const std::string& halign, const std::string& valign) {
Expand Down Expand Up @@ -55,6 +56,25 @@ IWidget::SFormatResult IWidget::formatString(std::string in) {
result.updateEveryMs = result.updateEveryMs != 0 && result.updateEveryMs < 1000 ? result.updateEveryMs : 1000;
}

if (in.starts_with("cmd[") && in.contains("]")) {
// this is a command
CVarList vars(in.substr(4, in.find_first_of(']') - 4));

for (const auto& v : vars) {
if (v.starts_with("update:")) {
try {
result.updateEveryMs = std::stoull(v.substr(7));
} catch (std::exception& e) { Debug::log(ERR, "Error parsing {} in cmd[]", v); }
} else {
Debug::log(ERR, "Unknown prop in string format {}", v);
}
}

result.alwaysUpdate = true;
in = in.substr(in.find_first_of(']') + 1);
result.cmd = true;
}

result.formatted = in;
return result;
}
2 changes: 2 additions & 0 deletions src/renderer/widgets/IWidget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class IWidget {
struct SFormatResult {
std::string formatted;
float updateEveryMs = 0; // 0 means don't (static)
bool alwaysUpdate = false;
bool cmd = false;
};

virtual SFormatResult formatString(std::string in);
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/widgets/Label.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void CLabel::onTimerUpdate() {

label = formatString(labelPreFormat);

if (label.formatted == oldFormatted)
if (label.formatted == oldFormatted && !label.alwaysUpdate)
return;

if (!pendingResourceID.empty())
Expand Down Expand Up @@ -60,6 +60,7 @@ CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string,
request.props["font_family"] = fontFamily;
request.props["color"] = labelColor;
request.props["font_size"] = fontSize;
request.props["cmd"] = label.cmd;

g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);

Expand Down

0 comments on commit 5370762

Please sign in to comment.