2023-09-02 20:22:26 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-06-27 23:52:01 +00:00
|
|
|
#include <gtkmm/button.h>
|
|
|
|
#include <gtkmm/label.h>
|
2023-09-22 21:18:02 +00:00
|
|
|
#include <json/value.h>
|
2023-07-03 22:24:34 +00:00
|
|
|
|
2023-09-22 19:37:26 +00:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
2023-09-02 20:22:26 +00:00
|
|
|
#include <map>
|
2023-07-03 22:17:26 +00:00
|
|
|
#include <memory>
|
2023-09-22 19:37:26 +00:00
|
|
|
#include <optional>
|
2023-10-11 13:59:33 +00:00
|
|
|
#include <regex>
|
2023-09-02 20:22:26 +00:00
|
|
|
#include <string>
|
2023-10-16 22:07:00 +00:00
|
|
|
#include <variant>
|
2023-09-02 20:22:26 +00:00
|
|
|
#include <vector>
|
2023-06-27 23:52:01 +00:00
|
|
|
|
|
|
|
#include "AModule.hpp"
|
|
|
|
#include "bar.hpp"
|
|
|
|
#include "modules/hyprland/backend.hpp"
|
2023-09-09 14:32:55 +00:00
|
|
|
#include "util/enum.hpp"
|
2023-10-09 16:53:00 +00:00
|
|
|
#include "util/regex_collection.hpp"
|
2023-06-27 23:52:01 +00:00
|
|
|
|
2023-09-22 19:37:26 +00:00
|
|
|
using WindowAddress = std::string;
|
2023-10-09 16:53:00 +00:00
|
|
|
|
2023-06-27 23:52:01 +00:00
|
|
|
namespace waybar::modules::hyprland {
|
|
|
|
|
2023-08-10 17:40:14 +00:00
|
|
|
class Workspaces;
|
|
|
|
|
2023-10-21 16:15:22 +00:00
|
|
|
class WindowCreationPayload {
|
2023-10-16 22:07:00 +00:00
|
|
|
public:
|
2023-10-21 16:15:22 +00:00
|
|
|
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
|
|
|
std::string window_repr);
|
|
|
|
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
|
|
|
std::string window_class, std::string window_title);
|
|
|
|
WindowCreationPayload(Json::Value const& client_data);
|
2023-10-16 22:07:00 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
int incrementTimeSpentUncreated();
|
|
|
|
bool isEmpty(Workspaces& workspace_manager);
|
|
|
|
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
2023-10-16 22:07:00 +00:00
|
|
|
std::string repr(Workspaces& workspace_manager);
|
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
std::string getWorkspaceName() const { return m_workspaceName; }
|
|
|
|
WindowAddress getAddress() const { return m_windowAddress; }
|
2023-10-16 22:07:00 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
void moveToWorksace(std::string& new_workspace_name);
|
2023-10-18 22:04:09 +00:00
|
|
|
|
2023-10-16 22:07:00 +00:00
|
|
|
private:
|
2023-12-04 11:10:16 +00:00
|
|
|
void clearAddr();
|
|
|
|
void clearWorkspaceName();
|
2023-10-16 22:07:00 +00:00
|
|
|
|
|
|
|
using Repr = std::string;
|
|
|
|
using ClassAndTitle = std::pair<std::string, std::string>;
|
2023-12-04 11:10:16 +00:00
|
|
|
std::variant<Repr, ClassAndTitle> m_window;
|
2023-10-16 22:07:00 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
WindowAddress m_windowAddress;
|
|
|
|
std::string m_workspaceName;
|
2023-10-21 14:52:23 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
int m_timeSpentUncreated = 0;
|
2023-10-16 22:07:00 +00:00
|
|
|
};
|
|
|
|
|
2023-06-27 23:52:01 +00:00
|
|
|
class Workspace {
|
|
|
|
public:
|
2023-09-22 19:37:26 +00:00
|
|
|
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
2023-10-21 14:52:23 +00:00
|
|
|
const Json::Value& clients_data = Json::Value::nullRef);
|
2023-12-04 11:10:16 +00:00
|
|
|
std::string& selectIcon(std::map<std::string, std::string>& icons_map);
|
|
|
|
Gtk::Button& button() { return m_button; };
|
|
|
|
|
|
|
|
int id() const { return m_id; };
|
|
|
|
std::string name() const { return m_name; };
|
|
|
|
std::string output() const { return m_output; };
|
2023-10-21 16:13:44 +00:00
|
|
|
bool isActive() const { return m_isActive; };
|
2023-12-04 11:10:16 +00:00
|
|
|
bool isSpecial() const { return m_isSpecial; };
|
|
|
|
bool isPersistent() const { return m_isPersistent; };
|
|
|
|
bool isVisible() const { return m_isVisible; };
|
|
|
|
bool isEmpty() const { return m_windows == 0; };
|
|
|
|
bool isUrgent() const { return m_isUrgent; };
|
|
|
|
|
|
|
|
bool handleClicked(GdkEventButton* bt) const;
|
2023-10-21 16:13:44 +00:00
|
|
|
void setActive(bool value = true) { m_isActive = value; };
|
2023-12-04 11:10:16 +00:00
|
|
|
void setPersistent(bool value = true) { m_isPersistent = value; };
|
|
|
|
void setUrgent(bool value = true) { m_isUrgent = value; };
|
|
|
|
void setVisible(bool value = true) { m_isVisible = value; };
|
|
|
|
void setWindows(uint value) { m_windows = value; };
|
|
|
|
void setName(std::string const& value) { m_name = value; };
|
|
|
|
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); }
|
|
|
|
void insertWindow(WindowCreationPayload create_window_paylod);
|
|
|
|
std::string removeWindow(WindowAddress const& addr);
|
|
|
|
void initializeWindowMap(const Json::Value& clients_data);
|
|
|
|
|
|
|
|
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
|
|
|
std::optional<std::string> closeWindow(WindowAddress const& addr);
|
2023-07-15 17:44:57 +00:00
|
|
|
|
2023-06-30 21:18:57 +00:00
|
|
|
void update(const std::string& format, const std::string& icon);
|
2023-06-27 23:52:01 +00:00
|
|
|
|
|
|
|
private:
|
2023-12-04 11:10:16 +00:00
|
|
|
Workspaces& m_workspaceManager;
|
|
|
|
|
|
|
|
int m_id;
|
|
|
|
std::string m_name;
|
|
|
|
std::string m_output;
|
|
|
|
uint m_windows;
|
2023-10-21 16:13:44 +00:00
|
|
|
bool m_isActive = false;
|
2023-12-04 11:10:16 +00:00
|
|
|
bool m_isSpecial = false;
|
|
|
|
bool m_isPersistent = false;
|
|
|
|
bool m_isUrgent = false;
|
|
|
|
bool m_isVisible = false;
|
|
|
|
|
|
|
|
std::map<WindowAddress, std::string> m_windowMap;
|
|
|
|
|
|
|
|
Gtk::Button m_button;
|
|
|
|
Gtk::Box m_content;
|
|
|
|
Gtk::Label m_label;
|
2023-06-27 23:52:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Workspaces : public AModule, public EventHandler {
|
|
|
|
public:
|
|
|
|
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
2023-07-16 12:47:14 +00:00
|
|
|
~Workspaces() override;
|
2023-06-27 23:52:01 +00:00
|
|
|
void update() override;
|
|
|
|
void init();
|
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
auto allOutputs() const -> bool { return m_allOutputs; }
|
|
|
|
auto showSpecial() const -> bool { return m_showSpecial; }
|
|
|
|
auto activeOnly() const -> bool { return m_activeOnly; }
|
2023-07-15 17:44:57 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
2023-07-15 17:44:57 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
std::string getRewrite(std::string window_class, std::string window_title);
|
|
|
|
std::string& getWindowSeparator() { return m_formatWindowSeparator; }
|
|
|
|
bool isWorkspaceIgnored(std::string const& workspace_name);
|
2023-09-22 21:18:02 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
|
2023-10-11 14:40:49 +00:00
|
|
|
|
2023-06-27 23:52:01 +00:00
|
|
|
private:
|
2023-10-21 14:52:23 +00:00
|
|
|
void onEvent(const std::string& e) override;
|
2023-12-04 11:10:16 +00:00
|
|
|
void updateWindowCount();
|
|
|
|
void sortWorkspaces();
|
2023-10-21 16:13:44 +00:00
|
|
|
void createWorkspace(Json::Value const& workspaceData,
|
|
|
|
Json::Value const& clientsData = Json::Value::nullRef);
|
2023-12-04 11:10:16 +00:00
|
|
|
void removeWorkspace(std::string const& name);
|
|
|
|
void setUrgentWorkspace(std::string const& windowaddress);
|
|
|
|
void parseConfig(const Json::Value& config);
|
|
|
|
void registerIpc();
|
2023-07-15 17:44:57 +00:00
|
|
|
|
2023-10-21 17:33:55 +00:00
|
|
|
// workspace events
|
2023-12-04 11:10:16 +00:00
|
|
|
void onWorkspaceActivated(std::string const& payload);
|
|
|
|
void onWorkspaceDestroyed(std::string const& payload);
|
2024-01-08 23:11:39 +00:00
|
|
|
void onWorkspaceCreated(std::string const& workspaceName,
|
|
|
|
Json::Value const& clientsData = Json::Value::nullRef);
|
2023-12-04 11:10:16 +00:00
|
|
|
void onWorkspaceMoved(std::string const& payload);
|
|
|
|
void onWorkspaceRenamed(std::string const& payload);
|
2023-10-21 17:33:55 +00:00
|
|
|
|
|
|
|
// monitor events
|
2023-12-04 11:10:16 +00:00
|
|
|
void onMonitorFocused(std::string const& payload);
|
2023-10-21 17:33:55 +00:00
|
|
|
|
|
|
|
// window events
|
2023-12-04 11:10:16 +00:00
|
|
|
void onWindowOpened(std::string const& payload);
|
|
|
|
void onWindowClosed(std::string const& addr);
|
|
|
|
void onWindowMoved(std::string const& payload);
|
|
|
|
|
|
|
|
void onWindowTitleEvent(std::string const& payload);
|
|
|
|
|
2023-10-21 16:13:44 +00:00
|
|
|
void onConfigReloaded();
|
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
int windowRewritePriorityFunction(std::string const& window_rule);
|
|
|
|
|
2024-01-05 05:49:11 +00:00
|
|
|
void doUpdate();
|
|
|
|
|
2024-01-08 20:10:13 +00:00
|
|
|
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
|
2023-10-21 16:13:44 +00:00
|
|
|
void registerOrphanWindow(WindowCreationPayload create_window_payload);
|
|
|
|
|
|
|
|
void initializeWorkspaces();
|
|
|
|
void setCurrentMonitorId();
|
|
|
|
void loadPersistentWorkspacesFromConfig(Json::Value const& clientsJson);
|
|
|
|
void loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& clientsJson);
|
2024-01-08 20:10:13 +00:00
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
bool m_allOutputs = false;
|
|
|
|
bool m_showSpecial = false;
|
|
|
|
bool m_activeOnly = false;
|
2023-10-21 16:13:44 +00:00
|
|
|
Json::Value m_persistentWorkspaceConfig;
|
2023-12-04 11:10:16 +00:00
|
|
|
|
2024-01-08 20:10:13 +00:00
|
|
|
// Map for windows stored in workspaces not present in the current bar.
|
|
|
|
// This happens when the user has multiple monitors (hence, multiple bars)
|
|
|
|
// and doesn't share windows accross bars (a.k.a `all-outputs` = false)
|
|
|
|
std::map<WindowAddress, std::string> m_orphanWindowMap;
|
|
|
|
|
2023-12-04 11:10:16 +00:00
|
|
|
enum class SortMethod { ID, NAME, NUMBER, DEFAULT };
|
|
|
|
util::EnumParser<SortMethod> m_enumParser;
|
|
|
|
SortMethod m_sortBy = SortMethod::DEFAULT;
|
|
|
|
std::map<std::string, SortMethod> m_sortMap = {{"ID", SortMethod::ID},
|
|
|
|
{"NAME", SortMethod::NAME},
|
|
|
|
{"NUMBER", SortMethod::NUMBER},
|
|
|
|
{"DEFAULT", SortMethod::DEFAULT}};
|
|
|
|
|
|
|
|
std::string m_format;
|
|
|
|
|
|
|
|
std::map<std::string, std::string> m_iconsMap;
|
|
|
|
util::RegexCollection m_windowRewriteRules;
|
|
|
|
bool m_anyWindowRewriteRuleUsesTitle = false;
|
|
|
|
std::string m_formatWindowSeparator;
|
|
|
|
|
|
|
|
bool m_withIcon;
|
|
|
|
uint64_t m_monitorId;
|
|
|
|
std::string m_activeWorkspaceName;
|
|
|
|
std::vector<std::unique_ptr<Workspace>> m_workspaces;
|
2024-01-08 23:11:39 +00:00
|
|
|
std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate;
|
2023-12-04 11:10:16 +00:00
|
|
|
std::vector<std::string> m_workspacesToRemove;
|
|
|
|
std::vector<WindowCreationPayload> m_windowsToCreate;
|
|
|
|
|
|
|
|
std::vector<std::regex> m_ignoreWorkspaces;
|
|
|
|
|
|
|
|
std::mutex m_mutex;
|
|
|
|
const Bar& m_bar;
|
|
|
|
Gtk::Box m_box;
|
2023-06-27 23:52:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace waybar::modules::hyprland
|