Initial implementation of active window
TODO: - Sometimes the active event arrives before the create, in which case the window is not activated. - The window title event also looks unreliable in some cases, will need to investigate
This commit is contained in:
@ -31,9 +31,11 @@ struct WindowRepr {
|
|||||||
std::string window_class;
|
std::string window_class;
|
||||||
std::string window_title;
|
std::string window_title;
|
||||||
std::string repr_rewrite;
|
std::string repr_rewrite;
|
||||||
|
bool isActive = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool empty() const { return address.empty(); }
|
bool empty() const { return address.empty(); }
|
||||||
|
void setActive(bool value) { isActive = value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WindowCreationPayload {
|
class WindowCreationPayload {
|
||||||
@ -48,6 +50,7 @@ class WindowCreationPayload {
|
|||||||
bool isEmpty(Workspaces& workspace_manager);
|
bool isEmpty(Workspaces& workspace_manager);
|
||||||
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
||||||
WindowRepr repr(Workspaces& workspace_manager);
|
WindowRepr repr(Workspaces& workspace_manager);
|
||||||
|
void setActive(bool value) { m_isActive = value; }
|
||||||
|
|
||||||
std::string getWorkspaceName() const { return m_workspaceName; }
|
std::string getWorkspaceName() const { return m_workspaceName; }
|
||||||
WindowAddress getAddress() const { return m_windowAddress; }
|
WindowAddress getAddress() const { return m_windowAddress; }
|
||||||
@ -64,6 +67,7 @@ class WindowCreationPayload {
|
|||||||
|
|
||||||
WindowAddress m_windowAddress;
|
WindowAddress m_windowAddress;
|
||||||
std::string m_workspaceName;
|
std::string m_workspaceName;
|
||||||
|
bool m_isActive = false;
|
||||||
|
|
||||||
int m_timeSpentUncreated = 0;
|
int m_timeSpentUncreated = 0;
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,7 @@ class Workspace {
|
|||||||
};
|
};
|
||||||
void insertWindow(WindowCreationPayload create_window_paylod);
|
void insertWindow(WindowCreationPayload create_window_paylod);
|
||||||
void initializeWindowMap(const Json::Value& clients_data);
|
void initializeWindowMap(const Json::Value& clients_data);
|
||||||
|
void setActiveWindow(WindowAddress const& addr);
|
||||||
|
|
||||||
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
||||||
std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
|
std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
|
||||||
|
@ -103,6 +103,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
void onWindowMoved(std::string const& payload);
|
void onWindowMoved(std::string const& payload);
|
||||||
|
|
||||||
void onWindowTitleEvent(std::string const& payload);
|
void onWindowTitleEvent(std::string const& payload);
|
||||||
|
void onActiveWindowChanged(WindowAddress const& payload);
|
||||||
|
|
||||||
void onConfigReloaded();
|
void onConfigReloaded();
|
||||||
|
|
||||||
@ -170,6 +171,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
|
|
||||||
IconLoader m_iconLoader;
|
IconLoader m_iconLoader;
|
||||||
bool m_enableTaskbar = false;
|
bool m_enableTaskbar = false;
|
||||||
|
bool m_updateActiveWindow = false;
|
||||||
bool m_taskbarWithIcon = false;
|
bool m_taskbarWithIcon = false;
|
||||||
bool m_taskbarWithTitle = false;
|
bool m_taskbarWithTitle = false;
|
||||||
std::string m_taskbarFormatBefore;
|
std::string m_taskbarFormatBefore;
|
||||||
|
@ -97,9 +97,9 @@ WindowRepr WindowCreationPayload::repr(Workspaces &workspace_manager) {
|
|||||||
return std::get<Repr>(m_window);
|
return std::get<Repr>(m_window);
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<ClassAndTitle>(m_window)) {
|
if (std::holds_alternative<ClassAndTitle>(m_window)) {
|
||||||
auto [window_class, window_title] = std::get<ClassAndTitle>(m_window);
|
auto const &[window_class, window_title] = std::get<ClassAndTitle>(m_window);
|
||||||
return {m_windowAddress, window_class, window_title,
|
return {m_windowAddress, window_class, window_title,
|
||||||
workspace_manager.getRewrite(window_class, window_title)};
|
workspace_manager.getRewrite(window_class, window_title), m_isActive};
|
||||||
}
|
}
|
||||||
// Unreachable
|
// Unreachable
|
||||||
spdlog::error("WorkspaceWindow::repr: Unreachable");
|
spdlog::error("WorkspaceWindow::repr: Unreachable");
|
||||||
|
@ -103,6 +103,16 @@ void Workspace::initializeWindowMap(const Json::Value &clients_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Workspace::setActiveWindow(WindowAddress const &addr) {
|
||||||
|
for (auto &window : m_windowMap) {
|
||||||
|
if (window.address == addr) {
|
||||||
|
window.setActive(true);
|
||||||
|
} else {
|
||||||
|
window.setActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Workspace::insertWindow(WindowCreationPayload create_window_paylod) {
|
void Workspace::insertWindow(WindowCreationPayload create_window_paylod) {
|
||||||
if (!create_window_paylod.isEmpty(m_workspaceManager)) {
|
if (!create_window_paylod.isEmpty(m_workspaceManager)) {
|
||||||
auto repr = create_window_paylod.repr(m_workspaceManager);
|
auto repr = create_window_paylod.repr(m_workspaceManager);
|
||||||
@ -259,6 +269,9 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
|||||||
auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
|
auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
window_box->set_tooltip_text(window_repr.window_title);
|
window_box->set_tooltip_text(window_repr.window_title);
|
||||||
window_box->get_style_context()->add_class("taskbar-window");
|
window_box->get_style_context()->add_class("taskbar-window");
|
||||||
|
if (window_repr.isActive) {
|
||||||
|
window_box->get_style_context()->add_class("active");
|
||||||
|
}
|
||||||
auto event_box = Gtk::manage(new Gtk::EventBox());
|
auto event_box = Gtk::manage(new Gtk::EventBox());
|
||||||
event_box->add(*window_box);
|
event_box->add(*window_box);
|
||||||
if (m_workspaceManager.onClickWindow() != "") {
|
if (m_workspaceManager.onClickWindow() != "") {
|
||||||
|
@ -341,6 +341,8 @@ void Workspaces::onEvent(const std::string &ev) {
|
|||||||
onWorkspaceRenamed(payload);
|
onWorkspaceRenamed(payload);
|
||||||
} else if (eventName == "windowtitlev2") {
|
} else if (eventName == "windowtitlev2") {
|
||||||
onWindowTitleEvent(payload);
|
onWindowTitleEvent(payload);
|
||||||
|
} else if (eventName == "activewindowv2") {
|
||||||
|
onActiveWindowChanged(payload);
|
||||||
} else if (eventName == "configreloaded") {
|
} else if (eventName == "configreloaded") {
|
||||||
onConfigReloaded();
|
onConfigReloaded();
|
||||||
}
|
}
|
||||||
@ -561,9 +563,10 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
|||||||
(*windowWorkspace)->insertWindow(std::move(wcp));
|
(*windowWorkspace)->insertWindow(std::move(wcp));
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
auto queuedWindow = std::ranges::find_if(m_windowsToCreate, [payload](auto &windowPayload) {
|
auto queuedWindow =
|
||||||
return windowPayload.getAddress() == payload;
|
std::ranges::find_if(m_windowsToCreate, [&windowAddress](auto &windowPayload) {
|
||||||
});
|
return windowPayload.getAddress() == windowAddress;
|
||||||
|
});
|
||||||
|
|
||||||
// If the window was queued, rename it in the queue
|
// If the window was queued, rename it in the queue
|
||||||
if (queuedWindow != m_windowsToCreate.end()) {
|
if (queuedWindow != m_windowsToCreate.end()) {
|
||||||
@ -586,6 +589,28 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Workspaces::onActiveWindowChanged(WindowAddress const &activeWindowAddress) {
|
||||||
|
spdlog::trace("Active window changed: {}", activeWindowAddress);
|
||||||
|
|
||||||
|
for (auto &[address, window] : m_orphanWindowMap) {
|
||||||
|
if (address == activeWindowAddress) {
|
||||||
|
window.setActive(true);
|
||||||
|
} else {
|
||||||
|
window.setActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto const &workspace : m_workspaces) {
|
||||||
|
workspace->setActiveWindow(activeWindowAddress);
|
||||||
|
}
|
||||||
|
for (auto &window : m_windowsToCreate) {
|
||||||
|
if (window.getAddress() == activeWindowAddress) {
|
||||||
|
window.setActive(true);
|
||||||
|
} else {
|
||||||
|
window.setActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Workspaces::onConfigReloaded() {
|
void Workspaces::onConfigReloaded() {
|
||||||
spdlog::info("Hyprland config reloaded, reinitializing hyprland/workspaces module...");
|
spdlog::info("Hyprland config reloaded, reinitializing hyprland/workspaces module...");
|
||||||
init();
|
init();
|
||||||
@ -701,6 +726,7 @@ auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
populateBoolConfig(workspaceTaskbar, "enable", m_enableTaskbar);
|
populateBoolConfig(workspaceTaskbar, "enable", m_enableTaskbar);
|
||||||
|
populateBoolConfig(workspaceTaskbar, "update-active-window", m_updateActiveWindow);
|
||||||
|
|
||||||
if (workspaceTaskbar["format"].isString()) {
|
if (workspaceTaskbar["format"].isString()) {
|
||||||
/* The user defined a format string, use it */
|
/* The user defined a format string, use it */
|
||||||
@ -765,6 +791,12 @@ auto Workspaces::registerIpc() -> void {
|
|||||||
"rewrite rule uses the 'title' field.");
|
"rewrite rule uses the 'title' field.");
|
||||||
m_ipc.registerForIPC("windowtitlev2", this);
|
m_ipc.registerForIPC("windowtitlev2", this);
|
||||||
}
|
}
|
||||||
|
if (m_updateActiveWindow) {
|
||||||
|
spdlog::info(
|
||||||
|
"Registering for Hyprland's 'activewindowv2' events because 'update-active-window' is set "
|
||||||
|
"to true.");
|
||||||
|
m_ipc.registerForIPC("activewindowv2", this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::removeWorkspacesToRemove() {
|
void Workspaces::removeWorkspacesToRemove() {
|
||||||
|
Reference in New Issue
Block a user