Parent directory

main.cpp

5331 bytes
  1#include <hyprland/src/Compositor.hpp>
  2#include <hyprland/src/config/values/ConfigValues.hpp>
  3#include <hyprland/src/plugins/PluginAPI.hpp>
  4#include <hyprland/src/render/Renderer.hpp>
  5#include <hyprland/src/render/OpenGL.hpp>
  6#include <hyprland/src/version.h>
  7
  8#include "dispatchers.hpp"
  9#include "globals.hpp"
 10#include "TabGroup.hpp"
 11
 12APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; }
 13
 14APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
 15	PHANDLE = handle;
 16
 17#ifndef HY3_NO_VERSION_CHECK
 18	const std::string COMPOSITOR_HASH = __hyprland_api_get_hash();
 19	const std::string CLIENT_HASH = __hyprland_api_get_client_hash();
 20
 21	if (COMPOSITOR_HASH != CLIENT_HASH) {
 22		HyprlandAPI::addNotification(
 23		    PHANDLE,
 24		    "[hy3] hy3 was compiled for a different version of hyprland; refusing to load.",
 25		    CHyprColor {1.0, 0.2, 0.2, 1.0},
 26		    10000
 27		);
 28
 29		throw std::runtime_error("[hy3] target hyprland version mismatch");
 30	}
 31#endif
 32
 33#define CONF(NAME, TYPE, VALUE)                                                                    \
 34	HyprlandAPI::addConfigValueV2(PHANDLE, makeShared<Config::Values::TYPE>("plugin:hy3:" NAME, "", VALUE))
 35
 36	// general
 37	CONF("no_gaps_when_only", Int, 0);
 38	CONF("node_collapse_policy", Int, 2);
 39	CONF("group_inset", Int, 10);
 40	CONF("tab_first_window", Bool, false);
 41
 42	// tabs
 43	CONF("tabs:height", Int, 22);
 44	CONF("tabs:padding", Int, 5);
 45	CONF("tabs:from_top", Bool, false);
 46	CONF("tabs:radius", Int, 6);
 47	CONF("tabs:border_width", Int, 2);
 48	CONF("tabs:render_text", Bool, true);
 49	CONF("tabs:text_center", Bool, true);
 50	CONF("tabs:text_font", String, "Sans");
 51	CONF("tabs:text_height", Int, 8);
 52	CONF("tabs:text_padding", Int, 3);
 53	CONF("tabs:opacity", Float, 1.0);
 54	CONF("tabs:blur", Bool, true);
 55	CONF("tabs:colors:active", Color, 0x4033ccff);
 56	CONF("tabs:colors:active_border", Color, 0xee33ccff);
 57	CONF("tabs:colors:active_text", Color, 0xffffffff);
 58	CONF("tabs:colors:active_alt_monitor", Color, 0x40606060);
 59	CONF("tabs:colors:active_alt_monitor_border", Color, 0xee808080);
 60	CONF("tabs:colors:active_alt_monitor_text", Color, 0xffffffff);
 61	CONF("tabs:colors:focused", Color, 0x40606060);
 62	CONF("tabs:colors:focused_border", Color, 0xee808080);
 63	CONF("tabs:colors:focused_text", Color, 0xffffffff);
 64	CONF("tabs:colors:inactive", Color, 0x20303030);
 65	CONF("tabs:colors:inactive_border", Color, 0xaa606060);
 66	CONF("tabs:colors:inactive_text", Color, 0xffffffff);
 67	CONF("tabs:colors:urgent", Color, 0x40ff2233);
 68	CONF("tabs:colors:urgent_border", Color, 0xeeff2233);
 69	CONF("tabs:colors:urgent_text", Color, 0xffffffff);
 70	CONF("tabs:colors:locked", Color, 0x40909033);
 71	CONF("tabs:colors:locked_border", Color, 0xee909033);
 72	CONF("tabs:colors:locked_text", Color, 0xffffffff);
 73
 74	// autotiling
 75	CONF("autotile:enable", Bool, false);
 76	CONF("autotile:ephemeral_groups", Bool, true);
 77	CONF("autotile:trigger_height", Int, 0);
 78	CONF("autotile:trigger_width", Int, 0);
 79	CONF("autotile:workspaces", String, "all");
 80
 81#undef CONF
 82
 83	HyprlandAPI::addTiledAlgo(PHANDLE, "hy3", &typeid(Hy3Layout), []() -> UP<Layout::ITiledAlgorithm> {
 84		return makeUnique<Hy3Layout>();
 85	});
 86
 87	g_renderListener = Event::bus()->m_events.render.stage.listen([](eRenderStage stage) {
 88		static bool rendering_normally = false;
 89		static std::vector<Hy3TabGroup*> rendered_groups;
 90
 91		switch (stage) {
 92		case RENDER_PRE_WINDOWS:
 93			rendering_normally = true;
 94			rendered_groups.clear();
 95			break;
 96		case RENDER_POST_WINDOW:
 97			if (!rendering_normally) break;
 98
 99			for (auto& wp: g_tabGroups) {
100				auto* entry = wp.get();
101				if (!entry) continue;
102				if (!entry->hidden
103				    && entry->target_window == g_pHyprRenderer->m_renderData.currentWindow.lock()
104				    && std::find(rendered_groups.begin(), rendered_groups.end(), entry)
105				           == rendered_groups.end())
106				{
107					g_pHyprRenderer->m_renderPass.add(makeUnique<Hy3TabPassElement>(entry));
108					rendered_groups.push_back(entry);
109				}
110			}
111			break;
112		case RENDER_POST_WINDOWS: rendering_normally = false; break;
113		default: break;
114		}
115	});
116
117	g_tickListener = Event::bus()->m_events.tick.listen([]() {
118		for (auto& wp: g_tabGroups) {
119			if (auto* tg = wp.get()) tg->tick();
120		}
121		std::erase_if(g_destroyingTabGroups, [](auto& up) { return up->bar.destroy; });
122		std::erase_if(g_tabGroups, [](auto& wp) { return !wp; });
123	});
124
125	g_windowTitleListener = Event::bus()->m_events.window.title.listen([](PHLWINDOW window) {
126		if (!window) return;
127		auto* hy3 = hy3InstanceForWorkspace(window->m_workspace);
128		if (!hy3) return;
129		auto* node = hy3->getNodeFromWindow(window.get());
130		if (!node) return;
131		node->updateTabBarRecursive();
132	});
133
134	g_urgentListener = Event::bus()->m_events.window.urgent.listen([](PHLWINDOW window) {
135		if (!window) return;
136		window->m_hints |= Desktop::View::WINDOW_HINT_URGENT;
137		auto* hy3 = hy3InstanceForWorkspace(window->m_workspace);
138		if (!hy3) return;
139		auto* node = hy3->getNodeFromWindow(window.get());
140		if (!node) return;
141		node->updateTabBarRecursive();
142	});
143
144	registerDispatchers();
145
146	HyprlandAPI::reloadConfig();
147
148	return {"hy3", "i3 like layout for hyprland", "outfoxxed", "0.1"};
149}
150
151APICALL EXPORT void PLUGIN_EXIT() {
152	g_renderListener.reset();
153	g_tickListener.reset();
154	g_windowTitleListener.reset();
155	g_urgentListener.reset();
156
157	g_tabGroups.clear();
158	g_destroyingTabGroups.clear();
159}