Plugin System (#1590)
--------- Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
This commit is contained in:
parent
74a10f26a4
commit
8b81f41e52
45 changed files with 1691 additions and 85 deletions
|
|
@ -4,10 +4,13 @@
|
|||
#include <execinfo.h>
|
||||
#include <fstream>
|
||||
|
||||
#include "../plugins/PluginSystem.hpp"
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
|
||||
std::string getRandomMessage() {
|
||||
|
||||
const std::vector<std::string> MESSAGES = {"Sorry, didn't mean to...",
|
||||
|
|
@ -43,6 +46,16 @@ void CrashReporter::createAndSaveCrash() {
|
|||
|
||||
finalCrashReport += "Hyprland received signal 11 (SIGSEGV): Segmentation Fault\n\n";
|
||||
|
||||
if (!g_pPluginSystem->getAllPlugins().empty()) {
|
||||
finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n";
|
||||
|
||||
for (auto& p : g_pPluginSystem->getAllPlugins()) {
|
||||
finalCrashReport += getFormat("\t%s (%s) %s\n", p->name.c_str(), p->author.c_str(), p->version.c_str());
|
||||
}
|
||||
|
||||
finalCrashReport += "\n\n";
|
||||
}
|
||||
|
||||
finalCrashReport += "System info:\n";
|
||||
|
||||
struct utsname unameInfo;
|
||||
|
|
|
|||
|
|
@ -1087,6 +1087,50 @@ std::string dispatchOutput(std::string request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchPlugin(std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 2)
|
||||
return "not enough args";
|
||||
|
||||
const auto OPERATION = vars[1];
|
||||
const auto PATH = vars[2];
|
||||
|
||||
if (OPERATION == "load") {
|
||||
if (vars.size() < 3)
|
||||
return "not enough args";
|
||||
|
||||
const auto PLUGIN = g_pPluginSystem->loadPlugin(PATH);
|
||||
|
||||
if (!PLUGIN)
|
||||
return "error in loading plugin";
|
||||
} else if (OPERATION == "unload") {
|
||||
if (vars.size() < 3)
|
||||
return "not enough args";
|
||||
|
||||
const auto PLUGIN = g_pPluginSystem->getPluginByPath(PATH);
|
||||
|
||||
if (!PLUGIN)
|
||||
return "plugin not loaded";
|
||||
|
||||
g_pPluginSystem->unloadPlugin(PLUGIN);
|
||||
} else if (OPERATION == "list") {
|
||||
const auto PLUGINS = g_pPluginSystem->getAllPlugins();
|
||||
|
||||
std::string list = "";
|
||||
for (auto& p : PLUGINS) {
|
||||
list += getFormat("\nPlugin %s by %s:\n\tHandle: %lx\n\tVersion: %s\n\tDescription: %s\n", p->name.c_str(), p->author.c_str(), p->m_pHandle, p->version.c_str(),
|
||||
p->description.c_str());
|
||||
}
|
||||
|
||||
return list;
|
||||
} else {
|
||||
return "unknown opt";
|
||||
}
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string getReply(std::string request) {
|
||||
auto format = HyprCtl::FORMAT_NORMAL;
|
||||
|
||||
|
|
@ -1134,6 +1178,8 @@ std::string getReply(std::string request) {
|
|||
return bindsRequest(format);
|
||||
else if (request == "animations")
|
||||
return animationsRequest(format);
|
||||
else if (request.find("plugin") == 0)
|
||||
return dispatchPlugin(request);
|
||||
else if (request.find("setprop") == 0)
|
||||
return dispatchSetProp(request);
|
||||
else if (request.find("seterror") == 0)
|
||||
|
|
@ -1156,6 +1202,10 @@ std::string getReply(std::string request) {
|
|||
return "unknown request";
|
||||
}
|
||||
|
||||
std::string HyprCtl::makeDynamicCall(const std::string& input) {
|
||||
return getReply(input);
|
||||
}
|
||||
|
||||
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
namespace HyprCtl {
|
||||
void startHyprCtlSocket();
|
||||
void startHyprCtlSocket();
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
|
||||
// very simple thread-safe request method
|
||||
inline bool requestMade = false;
|
||||
|
|
@ -18,8 +19,7 @@ namespace HyprCtl {
|
|||
|
||||
inline int iSocketFD = -1;
|
||||
|
||||
enum eHyprCtlOutputFormat
|
||||
{
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
|
|
|
|||
155
src/debug/HyprNotificationOverlay.cpp
Normal file
155
src/debug/HyprNotificationOverlay.cpp
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#include "HyprNotificationOverlay.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
|
||||
if (m_dNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||
});
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs) {
|
||||
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
|
||||
|
||||
PNOTIF->text = text;
|
||||
PNOTIF->color = color;
|
||||
PNOTIF->started.reset();
|
||||
PNOTIF->timeMs = timeMs;
|
||||
}
|
||||
|
||||
wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
static constexpr auto ANIM_DURATION_MS = 600.0;
|
||||
static constexpr auto ANIM_LAG_MS = 100.0;
|
||||
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
|
||||
|
||||
float offsetY = 10;
|
||||
float maxWidth = 0;
|
||||
|
||||
const auto SCALE = pMonitor->scale;
|
||||
const auto FONTSIZE = std::clamp((int)(10.f * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
|
||||
|
||||
const auto MONSIZE = pMonitor->vecPixelSize;
|
||||
|
||||
cairo_select_font_face(m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(m_pCairo, FONTSIZE);
|
||||
|
||||
cairo_text_extents_t cairoExtents;
|
||||
|
||||
const auto PBEZIER = g_pAnimationManager->getBezier("default");
|
||||
|
||||
for (auto& notif : m_dNotifications) {
|
||||
// first rect (bg, col)
|
||||
const float FIRSTRECTANIMP =
|
||||
(notif->started.getMillis() > (ANIM_DURATION_MS - ANIM_LAG_MS) ?
|
||||
(notif->started.getMillis() > notif->timeMs - (ANIM_DURATION_MS - ANIM_LAG_MS) ? notif->timeMs - notif->started.getMillis() : (ANIM_DURATION_MS - ANIM_LAG_MS)) :
|
||||
notif->started.getMillis()) /
|
||||
(ANIM_DURATION_MS - ANIM_LAG_MS);
|
||||
|
||||
const float FIRSTRECTPERC = FIRSTRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(FIRSTRECTANIMP);
|
||||
|
||||
// second rect (fg, black)
|
||||
const float SECONDRECTANIMP = (notif->started.getMillis() > ANIM_DURATION_MS ?
|
||||
(notif->started.getMillis() > notif->timeMs - ANIM_DURATION_MS ? notif->timeMs - notif->started.getMillis() : ANIM_DURATION_MS) :
|
||||
notif->started.getMillis()) /
|
||||
ANIM_DURATION_MS;
|
||||
|
||||
const float SECONDRECTPERC = SECONDRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(SECONDRECTANIMP);
|
||||
|
||||
// third rect (horiz, col)
|
||||
const float THIRDRECTPERC = notif->started.getMillis() / notif->timeMs;
|
||||
|
||||
// get text size
|
||||
cairo_text_extents(m_pCairo, notif->text.c_str(), &cairoExtents);
|
||||
|
||||
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||
|
||||
const auto NOTIFSIZE = Vector2D{cairoExtents.width + 20, cairoExtents.height + 10};
|
||||
|
||||
// draw rects
|
||||
cairo_rectangle(m_pCairo, MONSIZE.x - (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, offsetY, (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, NOTIFSIZE.y);
|
||||
cairo_fill(m_pCairo);
|
||||
|
||||
cairo_set_source_rgb(m_pCairo, 0.f, 0.f, 0.f);
|
||||
|
||||
cairo_rectangle(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC, offsetY, NOTIFSIZE.x * SECONDRECTPERC, NOTIFSIZE.y);
|
||||
cairo_fill(m_pCairo);
|
||||
|
||||
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||
|
||||
cairo_rectangle(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + 3, offsetY + NOTIFSIZE.y - 4, THIRDRECTPERC * (NOTIFSIZE.x - 6), 2);
|
||||
cairo_fill(m_pCairo);
|
||||
|
||||
// draw text
|
||||
cairo_set_source_rgb(m_pCairo, 1.f, 1.f, 1.f);
|
||||
cairo_move_to(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + NOTIF_LEFTBAR_SIZE, offsetY + FONTSIZE + (FONTSIZE / 10.0));
|
||||
cairo_show_text(m_pCairo, notif->text.c_str());
|
||||
|
||||
// adjust offset and move on
|
||||
offsetY += NOTIFSIZE.y + 10;
|
||||
|
||||
if (maxWidth < NOTIFSIZE.x)
|
||||
maxWidth = NOTIFSIZE.x;
|
||||
}
|
||||
|
||||
// cleanup notifs
|
||||
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||
|
||||
return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
if (m_pLastMonitor != pMonitor || !m_pCairo || !m_pCairoSurface) {
|
||||
|
||||
if (m_pCairo && m_pCairoSurface) {
|
||||
cairo_destroy(m_pCairo);
|
||||
cairo_surface_destroy(m_pCairoSurface);
|
||||
}
|
||||
|
||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_pCairo = cairo_create(m_pCairoSurface);
|
||||
m_pLastMonitor = pMonitor;
|
||||
}
|
||||
|
||||
// Draw the notifications
|
||||
if (m_dNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
// Render to the monitor
|
||||
|
||||
// clear the pixmap
|
||||
cairo_save(m_pCairo);
|
||||
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint(m_pCairo);
|
||||
cairo_restore(m_pCairo);
|
||||
|
||||
cairo_surface_flush(m_pCairoSurface);
|
||||
|
||||
wlr_box damage = drawNotifications(pMonitor);
|
||||
|
||||
g_pHyprRenderer->damageBox(&damage);
|
||||
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(pMonitor);
|
||||
|
||||
m_bLastDamage = damage;
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
|
||||
m_tTexture.allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
#ifndef GLES2
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
}
|
||||
40
src/debug/HyprNotificationOverlay.hpp
Normal file
40
src/debug/HyprNotificationOverlay.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Timer.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../render/Texture.hpp"
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
struct SNotification {
|
||||
std::string text = "";
|
||||
CColor color;
|
||||
CTimer started;
|
||||
float timeMs = 0;
|
||||
};
|
||||
|
||||
class CHyprNotificationOverlay {
|
||||
public:
|
||||
CHyprNotificationOverlay();
|
||||
|
||||
void draw(CMonitor* pMonitor);
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs);
|
||||
|
||||
private:
|
||||
wlr_box drawNotifications(CMonitor* pMonitor);
|
||||
wlr_box m_bLastDamage;
|
||||
|
||||
std::deque<std::unique_ptr<SNotification>> m_dNotifications;
|
||||
|
||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
||||
CMonitor* m_pLastMonitor = nullptr;
|
||||
|
||||
CTexture m_tTexture;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;
|
||||
Loading…
Add table
Add a link
Reference in a new issue