add workspace clicks
This commit is contained in:
@@ -48,6 +48,11 @@ class HyprlandService
|
|||||||
const Monitor *getMonitorById(int id) const;
|
const Monitor *getMonitorById(int id) const;
|
||||||
Monitor *getMonitorByIndex(std::size_t index);
|
Monitor *getMonitorByIndex(std::size_t index);
|
||||||
const Monitor *getMonitorByIndex(std::size_t index) const;
|
const Monitor *getMonitorByIndex(std::size_t index) const;
|
||||||
|
// Switch to a workspace slot on a given monitor. If the workspace has an
|
||||||
|
// associated Hyprland workspace id (hyprId >= 0) that id will be used.
|
||||||
|
// Otherwise the slot and monitor name will be used to request creation
|
||||||
|
// / activation via `hyprctl`.
|
||||||
|
void switchToWorkspace(int monitorId, int slot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_fd = -1;
|
int m_fd = -1;
|
||||||
|
|||||||
@@ -47,19 +47,13 @@ void Bar::setup_ui()
|
|||||||
main_box.set_end_widget(right_box);
|
main_box.set_end_widget(right_box);
|
||||||
main_box.set_valign(Gtk::Align::CENTER);
|
main_box.set_valign(Gtk::Align::CENTER);
|
||||||
|
|
||||||
left_box.set_margin_start(12);
|
|
||||||
left_box.set_margin_end(12);
|
|
||||||
left_box.set_valign(Gtk::Align::CENTER);
|
left_box.set_valign(Gtk::Align::CENTER);
|
||||||
|
|
||||||
// Don't expand the center box — keep it centered by alignment
|
// Don't expand the center box — keep it centered by alignment
|
||||||
center_box.set_hexpand(false);
|
center_box.set_hexpand(false);
|
||||||
center_box.set_margin_top(2);
|
|
||||||
center_box.set_margin_bottom(2);
|
|
||||||
center_box.set_valign(Gtk::Align::CENTER);
|
center_box.set_valign(Gtk::Align::CENTER);
|
||||||
center_box.set_halign(Gtk::Align::CENTER);
|
center_box.set_halign(Gtk::Align::CENTER);
|
||||||
|
|
||||||
right_box.set_margin_start(12);
|
|
||||||
right_box.set_margin_end(12);
|
|
||||||
right_box.set_valign(Gtk::Align::CENTER);
|
right_box.set_valign(Gtk::Align::CENTER);
|
||||||
|
|
||||||
m_workspaceIndicator = Gtk::make_managed<WorkspaceIndicator>(m_hyprlandService, m_monitorId);
|
m_workspaceIndicator = Gtk::make_managed<WorkspaceIndicator>(m_hyprlandService, m_monitorId);
|
||||||
@@ -86,6 +80,9 @@ void Bar::load_css()
|
|||||||
.workspace-pill-focused { background-color: rgba(255, 255, 255, 0.18); }
|
.workspace-pill-focused { background-color: rgba(255, 255, 255, 0.18); }
|
||||||
.workspace-pill-active { background-color: rgba(255, 255, 255, 0.25); }
|
.workspace-pill-active { background-color: rgba(255, 255, 255, 0.25); }
|
||||||
.workspace-pill-urgent { background-color: #ff5555; color: #111; }
|
.workspace-pill-urgent { background-color: #ff5555; color: #111; }
|
||||||
|
/* Hover effect: slightly brighten background and show pointer */
|
||||||
|
.workspace-pill:hover { background-color: rgba(255, 255, 255, 0.20); }
|
||||||
|
.workspace-pill:hover { cursor: pointer; } // TODO: cursors has to be set differently in GTK4?
|
||||||
.tray-icon { padding: 0; margin: 0; border: none; background: transparent; min-width: 0; min-height: 0; }
|
.tray-icon { padding: 0; margin: 0; border: none; background: transparent; min-width: 0; min-height: 0; }
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
|||||||
@@ -335,6 +335,54 @@ HyprlandService::Monitor *HyprlandService::getMonitorByIndex(std::size_t index)
|
|||||||
return &it->second;
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HyprlandService::switchToWorkspace(int monitorId, int slot)
|
||||||
|
{
|
||||||
|
auto it = m_monitors.find(monitorId);
|
||||||
|
if (it == m_monitors.end())
|
||||||
|
{
|
||||||
|
std::cerr << "[Hyprland] switchToWorkspace: monitor " << monitorId << " not found\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &monitor = it->second;
|
||||||
|
auto wsIt = monitor.workspaceStates.find(slot);
|
||||||
|
std::string cmd;
|
||||||
|
|
||||||
|
if (wsIt != monitor.workspaceStates.end() && wsIt->second.hyprId >= 0)
|
||||||
|
{
|
||||||
|
// Use the Hyprland workspace id if available
|
||||||
|
cmd = "hyprctl dispatch workspace " + std::to_string(wsIt->second.hyprId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback: ask Hyprland to switch/create a workspace on the monitor
|
||||||
|
// by using the slot number and the monitor name. Syntax: "<slot>:<monitor>"
|
||||||
|
// Example: hyprctl dispatch workspace 2:DP-1
|
||||||
|
// This may vary by Hyprland version; if it doesn't work on your system
|
||||||
|
// adjust the command accordingly.
|
||||||
|
std::string monName = monitor.name;
|
||||||
|
if (monName.empty())
|
||||||
|
{
|
||||||
|
// As a last resort, just try the slot number globally
|
||||||
|
cmd = "hyprctl dispatch workspace " + std::to_string(slot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Quote monitor name in case it contains spaces
|
||||||
|
cmd = "hyprctl dispatch workspace " + std::to_string(slot) + ":\"" + monName + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
(void)SystemHelper::get_command_output(cmd.c_str());
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
std::cerr << "[Hyprland] Failed to dispatch workspace command: " << ex.what() << " cmd=" << cmd << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const HyprlandService::Monitor *HyprlandService::getMonitorByIndex(std::size_t index) const
|
const HyprlandService::Monitor *HyprlandService::getMonitorByIndex(std::size_t index) const
|
||||||
{
|
{
|
||||||
if (index >= m_monitors.size())
|
if (index >= m_monitors.size())
|
||||||
|
|||||||
@@ -13,11 +13,9 @@ TrayIconWidget::TrayIconWidget(TrayService &service, std::string id)
|
|||||||
set_focusable(false);
|
set_focusable(false);
|
||||||
set_valign(Gtk::Align::CENTER);
|
set_valign(Gtk::Align::CENTER);
|
||||||
set_halign(Gtk::Align::CENTER);
|
set_halign(Gtk::Align::CENTER);
|
||||||
add_css_class("tray-icon");
|
|
||||||
|
|
||||||
m_picture.set_halign(Gtk::Align::CENTER);
|
m_picture.set_halign(Gtk::Align::CENTER);
|
||||||
m_picture.set_valign(Gtk::Align::CENTER);
|
m_picture.set_valign(Gtk::Align::CENTER);
|
||||||
m_picture.set_content_fit(Gtk::ContentFit::CONTAIN);
|
|
||||||
m_picture.set_can_shrink(true);
|
m_picture.set_can_shrink(true);
|
||||||
m_picture.set_size_request(20, 20);
|
m_picture.set_size_request(20, 20);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <gtkmm/widget.h>
|
#include <gtkmm/widget.h>
|
||||||
|
#include <gtkmm/gestureclick.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
#include <sigc++/functors/mem_fun.h>
|
#include <sigc++/functors/mem_fun.h>
|
||||||
|
|
||||||
WorkspaceIndicator::WorkspaceIndicator(HyprlandService &service, int monitorId)
|
WorkspaceIndicator::WorkspaceIndicator(HyprlandService &service, int monitorId)
|
||||||
@@ -79,6 +81,23 @@ void WorkspaceIndicator::rebuild()
|
|||||||
auto label = Gtk::make_managed<Gtk::Label>(display);
|
auto label = Gtk::make_managed<Gtk::Label>(display);
|
||||||
label->add_css_class("workspace-pill");
|
label->add_css_class("workspace-pill");
|
||||||
|
|
||||||
|
// Make the label clickable using a gesture click (primary button)
|
||||||
|
auto gesture = Gtk::GestureClick::create();
|
||||||
|
gesture->set_button(GDK_BUTTON_PRIMARY);
|
||||||
|
// Use a lambda to capture the workspace slot id
|
||||||
|
gesture->signal_released().connect([this, workspaceId](int /*n_press*/, double /*x*/, double /*y*/)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_service.switchToWorkspace(m_monitorId, workspaceId);
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
std::cerr << "[WorkspaceIndicator] switchToWorkspace failed: " << ex.what() << std::endl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
label->add_controller(gesture);
|
||||||
|
|
||||||
if (state != nullptr)
|
if (state != nullptr)
|
||||||
{
|
{
|
||||||
if (state->focused)
|
if (state->focused)
|
||||||
|
|||||||
Reference in New Issue
Block a user