summaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2023-02-27 12:32:38 +0000
committerGitHub <noreply@github.com>2023-02-27 12:32:38 +0000
commit8b81f41e52b55835aaaa7e4962af23a00188cbdc (patch)
treebca65923843ea931c0e0222f29d4e2901cfa8637 /src/debug
parent74a10f26a469de54968e584525f6507928f615f0 (diff)
Plugin System (#1590)
--------- Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/CrashReporter.cpp13
-rw-r--r--src/debug/HyprCtl.cpp50
-rw-r--r--src/debug/HyprCtl.hpp6
-rw-r--r--src/debug/HyprNotificationOverlay.cpp155
-rw-r--r--src/debug/HyprNotificationOverlay.hpp40
5 files changed, 261 insertions, 3 deletions
diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp
index 5738f180..084e44ad 100644
--- a/src/debug/CrashReporter.cpp
+++ b/src/debug/CrashReporter.cpp
@@ -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;
diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp
index 91af3938..f6ed285b 100644
--- a/src/debug/HyprCtl.cpp
+++ b/src/debug/HyprCtl.cpp
@@ -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;
diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp
index 26859692..00cf7c5b 100644
--- a/src/debug/HyprCtl.hpp
+++ b/src/debug/HyprCtl.hpp
@@ -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
};
diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp
new file mode 100644
index 00000000..94cb6a6c
--- /dev/null
+++ b/src/debug/HyprNotificationOverlay.cpp
@@ -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);
+} \ No newline at end of file
diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp
new file mode 100644
index 00000000..12ad8e38
--- /dev/null
+++ b/src/debug/HyprNotificationOverlay.hpp
@@ -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; \ No newline at end of file