commit
dc203b8439
|
@ -48,3 +48,5 @@ packagecache
|
||||||
# Nix
|
# Nix
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
||||||
|
.ccls-cache
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/hyprland/backend.hpp"
|
||||||
|
#include "util/enum.hpp"
|
||||||
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
|
using WindowAddress = std::string;
|
||||||
|
|
||||||
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
|
class Workspaces;
|
||||||
|
|
||||||
|
class WindowCreationPayload {
|
||||||
|
public:
|
||||||
|
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);
|
||||||
|
|
||||||
|
int incrementTimeSpentUncreated();
|
||||||
|
bool isEmpty(Workspaces& workspace_manager);
|
||||||
|
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
||||||
|
std::string repr(Workspaces& workspace_manager);
|
||||||
|
|
||||||
|
std::string getWorkspaceName() const { return m_workspaceName; }
|
||||||
|
WindowAddress getAddress() const { return m_windowAddress; }
|
||||||
|
|
||||||
|
void moveToWorksace(std::string& new_workspace_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void clearAddr();
|
||||||
|
void clearWorkspaceName();
|
||||||
|
|
||||||
|
using Repr = std::string;
|
||||||
|
using ClassAndTitle = std::pair<std::string, std::string>;
|
||||||
|
std::variant<Repr, ClassAndTitle> m_window;
|
||||||
|
|
||||||
|
WindowAddress m_windowAddress;
|
||||||
|
std::string m_workspaceName;
|
||||||
|
|
||||||
|
int m_timeSpentUncreated = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
|
@ -0,0 +1,88 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/hyprland/backend.hpp"
|
||||||
|
#include "modules/hyprland/windowcreationpayload.hpp"
|
||||||
|
#include "util/enum.hpp"
|
||||||
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
|
using WindowAddress = std::string;
|
||||||
|
|
||||||
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
|
class Workspaces;
|
||||||
|
class Workspace {
|
||||||
|
public:
|
||||||
|
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
||||||
|
const Json::Value& clients_data = Json::Value::nullRef);
|
||||||
|
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; };
|
||||||
|
bool isActive() const { return m_isActive; };
|
||||||
|
bool isSpecial() const { return m_isSpecial; };
|
||||||
|
bool isPersistent() const { return m_isPersistentRule || m_isPersistentConfig; };
|
||||||
|
bool isPersistentConfig() const { return m_isPersistentConfig; };
|
||||||
|
bool isPersistentRule() const { return m_isPersistentRule; };
|
||||||
|
bool isVisible() const { return m_isVisible; };
|
||||||
|
bool isEmpty() const { return m_windows == 0; };
|
||||||
|
bool isUrgent() const { return m_isUrgent; };
|
||||||
|
|
||||||
|
bool handleClicked(GdkEventButton* bt) const;
|
||||||
|
void setActive(bool value = true) { m_isActive = value; };
|
||||||
|
void setPersistentRule(bool value = true) { m_isPersistentRule = value; };
|
||||||
|
void setPersistentConfig(bool value = true) { m_isPersistentConfig = 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; };
|
||||||
|
void setOutput(std::string const& value) { m_output = 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);
|
||||||
|
|
||||||
|
void update(const std::string& format, const std::string& icon);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Workspaces& m_workspaceManager;
|
||||||
|
|
||||||
|
int m_id;
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_output;
|
||||||
|
uint m_windows;
|
||||||
|
bool m_isActive = false;
|
||||||
|
bool m_isSpecial = false;
|
||||||
|
bool m_isPersistentRule = false; // represents the persistent state in hyprland
|
||||||
|
bool m_isPersistentConfig = false; // represents the persistent state in the Waybar config
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
|
@ -17,6 +17,8 @@
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/hyprland/backend.hpp"
|
#include "modules/hyprland/backend.hpp"
|
||||||
|
#include "modules/hyprland/windowcreationpayload.hpp"
|
||||||
|
#include "modules/hyprland/workspace.hpp"
|
||||||
#include "util/enum.hpp"
|
#include "util/enum.hpp"
|
||||||
#include "util/regex_collection.hpp"
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
|
@ -26,97 +28,6 @@ namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
class Workspaces;
|
class Workspaces;
|
||||||
|
|
||||||
class WindowCreationPayload {
|
|
||||||
public:
|
|
||||||
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);
|
|
||||||
|
|
||||||
int incrementTimeSpentUncreated();
|
|
||||||
bool isEmpty(Workspaces& workspace_manager);
|
|
||||||
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
|
||||||
std::string repr(Workspaces& workspace_manager);
|
|
||||||
|
|
||||||
std::string getWorkspaceName() const { return m_workspaceName; }
|
|
||||||
WindowAddress getAddress() const { return m_windowAddress; }
|
|
||||||
|
|
||||||
void moveToWorksace(std::string& new_workspace_name);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void clearAddr();
|
|
||||||
void clearWorkspaceName();
|
|
||||||
|
|
||||||
using Repr = std::string;
|
|
||||||
using ClassAndTitle = std::pair<std::string, std::string>;
|
|
||||||
std::variant<Repr, ClassAndTitle> m_window;
|
|
||||||
|
|
||||||
WindowAddress m_windowAddress;
|
|
||||||
std::string m_workspaceName;
|
|
||||||
|
|
||||||
int m_timeSpentUncreated = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Workspace {
|
|
||||||
public:
|
|
||||||
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
|
||||||
const Json::Value& clients_data = Json::Value::nullRef);
|
|
||||||
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; };
|
|
||||||
bool isActive() const { return m_isActive; };
|
|
||||||
bool isSpecial() const { return m_isSpecial; };
|
|
||||||
bool isPersistent() const { return m_isPersistentRule || m_isPersistentConfig; };
|
|
||||||
bool isPersistentConfig() const { return m_isPersistentConfig; };
|
|
||||||
bool isPersistentRule() const { return m_isPersistentRule; };
|
|
||||||
bool isVisible() const { return m_isVisible; };
|
|
||||||
bool isEmpty() const { return m_windows == 0; };
|
|
||||||
bool isUrgent() const { return m_isUrgent; };
|
|
||||||
|
|
||||||
bool handleClicked(GdkEventButton* bt) const;
|
|
||||||
void setActive(bool value = true) { m_isActive = value; };
|
|
||||||
void setPersistentRule(bool value = true) { m_isPersistentRule = value; };
|
|
||||||
void setPersistentConfig(bool value = true) { m_isPersistentConfig = 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; };
|
|
||||||
void setOutput(std::string const& value) { m_output = 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);
|
|
||||||
|
|
||||||
void update(const std::string& format, const std::string& icon);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Workspaces& m_workspaceManager;
|
|
||||||
|
|
||||||
int m_id;
|
|
||||||
std::string m_name;
|
|
||||||
std::string m_output;
|
|
||||||
uint m_windows;
|
|
||||||
bool m_isActive = false;
|
|
||||||
bool m_isSpecial = false;
|
|
||||||
bool m_isPersistentRule = false; // represents the persistent state in hyprland
|
|
||||||
bool m_isPersistentConfig = false; // represents the persistent state in the Waybar config
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Workspaces : public AModule, public EventHandler {
|
class Workspaces : public AModule, public EventHandler {
|
||||||
public:
|
public:
|
||||||
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
|
@ -143,9 +54,21 @@ class Workspaces : public AModule, public EventHandler {
|
||||||
void sortWorkspaces();
|
void sortWorkspaces();
|
||||||
void createWorkspace(Json::Value const& workspaceData,
|
void createWorkspace(Json::Value const& workspaceData,
|
||||||
Json::Value const& clientsData = Json::Value::nullRef);
|
Json::Value const& clientsData = Json::Value::nullRef);
|
||||||
|
|
||||||
|
Json::Value createMonitorWorkspaceData(std::string const& name, std::string const& monitor);
|
||||||
void removeWorkspace(std::string const& name);
|
void removeWorkspace(std::string const& name);
|
||||||
void setUrgentWorkspace(std::string const& windowaddress);
|
void setUrgentWorkspace(std::string const& windowaddress);
|
||||||
|
|
||||||
|
// Config
|
||||||
void parseConfig(const Json::Value& config);
|
void parseConfig(const Json::Value& config);
|
||||||
|
auto populateIconsMap(const Json::Value& formatIcons) -> void;
|
||||||
|
auto populateBoolConfig(const Json::Value& config, const std::string& key, bool& member) -> void;
|
||||||
|
auto populateSortByConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
|
||||||
|
auto populatePersistentWorkspacesConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
|
||||||
|
|
||||||
void registerIpc();
|
void registerIpc();
|
||||||
|
|
||||||
// workspace events
|
// workspace events
|
||||||
|
@ -171,7 +94,13 @@ class Workspaces : public AModule, public EventHandler {
|
||||||
|
|
||||||
int windowRewritePriorityFunction(std::string const& window_rule);
|
int windowRewritePriorityFunction(std::string const& window_rule);
|
||||||
|
|
||||||
|
// Update methods
|
||||||
void doUpdate();
|
void doUpdate();
|
||||||
|
void removeWorkspacesToRemove();
|
||||||
|
void createWorkspacesToCreate();
|
||||||
|
std::vector<std::string> getVisibleWorkspaces();
|
||||||
|
void updateWorkspaceStates(const std::vector<std::string>& visibleWorkspaces);
|
||||||
|
bool updateWindowsToCreate();
|
||||||
|
|
||||||
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
|
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
|
||||||
void registerOrphanWindow(WindowCreationPayload create_window_payload);
|
void registerOrphanWindow(WindowCreationPayload create_window_payload);
|
||||||
|
|
|
@ -305,7 +305,9 @@ if true
|
||||||
'src/modules/hyprland/language.cpp',
|
'src/modules/hyprland/language.cpp',
|
||||||
'src/modules/hyprland/submap.cpp',
|
'src/modules/hyprland/submap.cpp',
|
||||||
'src/modules/hyprland/window.cpp',
|
'src/modules/hyprland/window.cpp',
|
||||||
|
'src/modules/hyprland/workspace.cpp',
|
||||||
'src/modules/hyprland/workspaces.cpp',
|
'src/modules/hyprland/workspaces.cpp',
|
||||||
|
'src/modules/hyprland/windowcreationpayload.cpp',
|
||||||
)
|
)
|
||||||
man_files += files(
|
man_files += files(
|
||||||
'man/waybar-hyprland-language.5.scd',
|
'man/waybar-hyprland-language.5.scd',
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include "modules/hyprland/windowcreationpayload.hpp"
|
||||||
|
|
||||||
|
#include <json/value.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "modules/hyprland/workspaces.hpp"
|
||||||
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
|
WindowCreationPayload::WindowCreationPayload(Json::Value const &client_data)
|
||||||
|
: m_window(std::make_pair(client_data["class"].asString(), client_data["title"].asString())),
|
||||||
|
m_windowAddress(client_data["address"].asString()),
|
||||||
|
m_workspaceName(client_data["workspace"]["name"].asString()) {
|
||||||
|
clearAddr();
|
||||||
|
clearWorkspaceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowCreationPayload::WindowCreationPayload(std::string workspace_name,
|
||||||
|
WindowAddress window_address, std::string window_repr)
|
||||||
|
: m_window(std::move(window_repr)),
|
||||||
|
m_windowAddress(std::move(window_address)),
|
||||||
|
m_workspaceName(std::move(workspace_name)) {
|
||||||
|
clearAddr();
|
||||||
|
clearWorkspaceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowCreationPayload::WindowCreationPayload(std::string workspace_name,
|
||||||
|
WindowAddress window_address, std::string window_class,
|
||||||
|
std::string window_title)
|
||||||
|
: m_window(std::make_pair(std::move(window_class), std::move(window_title))),
|
||||||
|
m_windowAddress(std::move(window_address)),
|
||||||
|
m_workspaceName(std::move(workspace_name)) {
|
||||||
|
clearAddr();
|
||||||
|
clearWorkspaceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowCreationPayload::clearAddr() {
|
||||||
|
// substr(2, ...) is necessary because Hyprland's JSON follows this format:
|
||||||
|
// 0x{ADDR}
|
||||||
|
// While Hyprland's IPC follows this format:
|
||||||
|
// {ADDR}
|
||||||
|
static const std::string ADDR_PREFIX = "0x";
|
||||||
|
static const int ADDR_PREFIX_LEN = ADDR_PREFIX.length();
|
||||||
|
|
||||||
|
if (m_windowAddress.starts_with(ADDR_PREFIX)) {
|
||||||
|
m_windowAddress =
|
||||||
|
m_windowAddress.substr(ADDR_PREFIX_LEN, m_windowAddress.length() - ADDR_PREFIX_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowCreationPayload::clearWorkspaceName() {
|
||||||
|
// The workspace name may optionally feature "special:" at the beginning.
|
||||||
|
// If so, we need to remove it because the workspace is saved WITHOUT the
|
||||||
|
// special qualifier. The reasoning is that not all of Hyprland's IPC events
|
||||||
|
// use this qualifier, so it's better to be consistent about our uses.
|
||||||
|
|
||||||
|
static const std::string SPECIAL_QUALIFIER_PREFIX = "special:";
|
||||||
|
static const int SPECIAL_QUALIFIER_PREFIX_LEN = SPECIAL_QUALIFIER_PREFIX.length();
|
||||||
|
|
||||||
|
if (m_workspaceName.starts_with(SPECIAL_QUALIFIER_PREFIX)) {
|
||||||
|
m_workspaceName = m_workspaceName.substr(
|
||||||
|
SPECIAL_QUALIFIER_PREFIX_LEN, m_workspaceName.length() - SPECIAL_QUALIFIER_PREFIX_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t spaceFound = m_workspaceName.find(' ');
|
||||||
|
if (spaceFound != std::string::npos) {
|
||||||
|
m_workspaceName.erase(m_workspaceName.begin() + spaceFound, m_workspaceName.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowCreationPayload::isEmpty(Workspaces &workspace_manager) {
|
||||||
|
if (std::holds_alternative<Repr>(m_window)) {
|
||||||
|
return std::get<Repr>(m_window).empty();
|
||||||
|
}
|
||||||
|
if (std::holds_alternative<ClassAndTitle>(m_window)) {
|
||||||
|
auto [window_class, window_title] = std::get<ClassAndTitle>(m_window);
|
||||||
|
return (window_class.empty() &&
|
||||||
|
(!workspace_manager.windowRewriteConfigUsesTitle() || window_title.empty()));
|
||||||
|
}
|
||||||
|
// Unreachable
|
||||||
|
spdlog::error("WorkspaceWindow::isEmpty: Unreachable");
|
||||||
|
throw std::runtime_error("WorkspaceWindow::isEmpty: Unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
int WindowCreationPayload::incrementTimeSpentUncreated() { return m_timeSpentUncreated++; }
|
||||||
|
|
||||||
|
void WindowCreationPayload::moveToWorksace(std::string &new_workspace_name) {
|
||||||
|
m_workspaceName = new_workspace_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string WindowCreationPayload::repr(Workspaces &workspace_manager) {
|
||||||
|
if (std::holds_alternative<Repr>(m_window)) {
|
||||||
|
return std::get<Repr>(m_window);
|
||||||
|
}
|
||||||
|
if (std::holds_alternative<ClassAndTitle>(m_window)) {
|
||||||
|
auto [window_class, window_title] = std::get<ClassAndTitle>(m_window);
|
||||||
|
return workspace_manager.getRewrite(window_class, window_title);
|
||||||
|
}
|
||||||
|
// Unreachable
|
||||||
|
spdlog::error("WorkspaceWindow::repr: Unreachable");
|
||||||
|
throw std::runtime_error("WorkspaceWindow::repr: Unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
|
@ -0,0 +1,214 @@
|
||||||
|
#include <json/value.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "modules/hyprland/workspaces.hpp"
|
||||||
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
|
Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_manager,
|
||||||
|
const Json::Value &clients_data)
|
||||||
|
: m_workspaceManager(workspace_manager),
|
||||||
|
m_id(workspace_data["id"].asInt()),
|
||||||
|
m_name(workspace_data["name"].asString()),
|
||||||
|
m_output(workspace_data["monitor"].asString()), // TODO:allow using monitor desc
|
||||||
|
m_windows(workspace_data["windows"].asInt()),
|
||||||
|
m_isActive(true),
|
||||||
|
m_isPersistentRule(workspace_data["persistent-rule"].asBool()),
|
||||||
|
m_isPersistentConfig(workspace_data["persistent-config"].asBool()) {
|
||||||
|
if (m_name.starts_with("name:")) {
|
||||||
|
m_name = m_name.substr(5);
|
||||||
|
} else if (m_name.starts_with("special")) {
|
||||||
|
m_name = m_id == -99 ? m_name : m_name.substr(8);
|
||||||
|
m_isSpecial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_button.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
|
m_button.signal_button_press_event().connect(sigc::mem_fun(*this, &Workspace::handleClicked),
|
||||||
|
false);
|
||||||
|
|
||||||
|
m_button.set_relief(Gtk::RELIEF_NONE);
|
||||||
|
m_content.set_center_widget(m_label);
|
||||||
|
m_button.add(m_content);
|
||||||
|
|
||||||
|
initializeWindowMap(clients_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addOrRemoveClass(const Glib::RefPtr<Gtk::StyleContext> &context, bool condition,
|
||||||
|
const std::string &class_name) {
|
||||||
|
if (condition) {
|
||||||
|
context->add_class(class_name);
|
||||||
|
} else {
|
||||||
|
context->remove_class(class_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> Workspace::closeWindow(WindowAddress const &addr) {
|
||||||
|
if (m_windowMap.contains(addr)) {
|
||||||
|
return removeWindow(addr);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Workspace::handleClicked(GdkEventButton *bt) const {
|
||||||
|
if (bt->type == GDK_BUTTON_PRESS) {
|
||||||
|
try {
|
||||||
|
if (id() > 0) { // normal
|
||||||
|
if (m_workspaceManager.moveToMonitor()) {
|
||||||
|
gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id()));
|
||||||
|
} else {
|
||||||
|
gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
|
||||||
|
}
|
||||||
|
} else if (!isSpecial()) { // named (this includes persistent)
|
||||||
|
if (m_workspaceManager.moveToMonitor()) {
|
||||||
|
gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name());
|
||||||
|
} else {
|
||||||
|
gIPC->getSocket1Reply("dispatch workspace name:" + name());
|
||||||
|
}
|
||||||
|
} else if (id() != -99) { // named special
|
||||||
|
gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
|
||||||
|
} else { // special
|
||||||
|
gIPC->getSocket1Reply("dispatch togglespecialworkspace");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
spdlog::error("Failed to dispatch workspace: {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::initializeWindowMap(const Json::Value &clients_data) {
|
||||||
|
m_windowMap.clear();
|
||||||
|
for (auto client : clients_data) {
|
||||||
|
if (client["workspace"]["id"].asInt() == id()) {
|
||||||
|
insertWindow({client});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::insertWindow(WindowCreationPayload create_window_paylod) {
|
||||||
|
if (!create_window_paylod.isEmpty(m_workspaceManager)) {
|
||||||
|
m_windowMap[create_window_paylod.getAddress()] = create_window_paylod.repr(m_workspaceManager);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Workspace::onWindowOpened(WindowCreationPayload const &create_window_paylod) {
|
||||||
|
if (create_window_paylod.getWorkspaceName() == name()) {
|
||||||
|
insertWindow(create_window_paylod);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Workspace::removeWindow(WindowAddress const &addr) {
|
||||||
|
std::string windowRepr = m_windowMap[addr];
|
||||||
|
m_windowMap.erase(addr);
|
||||||
|
return windowRepr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map) {
|
||||||
|
spdlog::trace("Selecting icon for workspace {}", name());
|
||||||
|
if (isUrgent()) {
|
||||||
|
auto urgentIconIt = icons_map.find("urgent");
|
||||||
|
if (urgentIconIt != icons_map.end()) {
|
||||||
|
return urgentIconIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActive()) {
|
||||||
|
auto activeIconIt = icons_map.find("active");
|
||||||
|
if (activeIconIt != icons_map.end()) {
|
||||||
|
return activeIconIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSpecial()) {
|
||||||
|
auto specialIconIt = icons_map.find("special");
|
||||||
|
if (specialIconIt != icons_map.end()) {
|
||||||
|
return specialIconIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto namedIconIt = icons_map.find(name());
|
||||||
|
if (namedIconIt != icons_map.end()) {
|
||||||
|
return namedIconIt->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVisible()) {
|
||||||
|
auto visibleIconIt = icons_map.find("visible");
|
||||||
|
if (visibleIconIt != icons_map.end()) {
|
||||||
|
return visibleIconIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty()) {
|
||||||
|
auto emptyIconIt = icons_map.find("empty");
|
||||||
|
if (emptyIconIt != icons_map.end()) {
|
||||||
|
return emptyIconIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPersistent()) {
|
||||||
|
auto persistentIconIt = icons_map.find("persistent");
|
||||||
|
if (persistentIconIt != icons_map.end()) {
|
||||||
|
return persistentIconIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto defaultIconIt = icons_map.find("default");
|
||||||
|
if (defaultIconIt != icons_map.end()) {
|
||||||
|
return defaultIconIt->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::update(const std::string &format, const std::string &icon) {
|
||||||
|
// clang-format off
|
||||||
|
if (this->m_workspaceManager.activeOnly() && \
|
||||||
|
!this->isActive() && \
|
||||||
|
!this->isPersistent() && \
|
||||||
|
!this->isVisible() && \
|
||||||
|
!this->isSpecial()) {
|
||||||
|
// clang-format on
|
||||||
|
// if activeOnly is true, hide if not active, persistent, visible or special
|
||||||
|
m_button.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_button.show();
|
||||||
|
|
||||||
|
auto styleContext = m_button.get_style_context();
|
||||||
|
addOrRemoveClass(styleContext, isActive(), "active");
|
||||||
|
addOrRemoveClass(styleContext, isSpecial(), "special");
|
||||||
|
addOrRemoveClass(styleContext, isEmpty(), "empty");
|
||||||
|
addOrRemoveClass(styleContext, isPersistent(), "persistent");
|
||||||
|
addOrRemoveClass(styleContext, isUrgent(), "urgent");
|
||||||
|
addOrRemoveClass(styleContext, isVisible(), "visible");
|
||||||
|
addOrRemoveClass(styleContext, m_workspaceManager.getBarOutput() == output(), "hosting-monitor");
|
||||||
|
|
||||||
|
std::string windows;
|
||||||
|
auto windowSeparator = m_workspaceManager.getWindowSeparator();
|
||||||
|
|
||||||
|
bool isNotFirst = false;
|
||||||
|
|
||||||
|
for (auto &[_pid, window_repr] : m_windowMap) {
|
||||||
|
if (isNotFirst) {
|
||||||
|
windows.append(windowSeparator);
|
||||||
|
}
|
||||||
|
isNotFirst = true;
|
||||||
|
windows.append(window_repr);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_label.set_markup(fmt::format(fmt::runtime(format), fmt::arg("id", id()),
|
||||||
|
fmt::arg("name", name()), fmt::arg("icon", icon),
|
||||||
|
fmt::arg("windows", windows)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue