add workspace clicks
This commit is contained in:
@@ -48,6 +48,11 @@ class HyprlandService
|
||||
const Monitor *getMonitorById(int id) const;
|
||||
Monitor *getMonitorByIndex(std::size_t index);
|
||||
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:
|
||||
int m_fd = -1;
|
||||
|
||||
@@ -47,19 +47,13 @@ void Bar::setup_ui()
|
||||
main_box.set_end_widget(right_box);
|
||||
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);
|
||||
|
||||
// Don't expand the center box — keep it centered by alignment
|
||||
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_halign(Gtk::Align::CENTER);
|
||||
|
||||
right_box.set_margin_start(12);
|
||||
right_box.set_margin_end(12);
|
||||
right_box.set_valign(Gtk::Align::CENTER);
|
||||
|
||||
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-active { background-color: rgba(255, 255, 255, 0.25); }
|
||||
.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; }
|
||||
)");
|
||||
|
||||
|
||||
@@ -335,6 +335,54 @@ HyprlandService::Monitor *HyprlandService::getMonitorByIndex(std::size_t index)
|
||||
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
|
||||
{
|
||||
if (index >= m_monitors.size())
|
||||
|
||||
@@ -13,11 +13,9 @@ TrayIconWidget::TrayIconWidget(TrayService &service, std::string id)
|
||||
set_focusable(false);
|
||||
set_valign(Gtk::Align::CENTER);
|
||||
set_halign(Gtk::Align::CENTER);
|
||||
add_css_class("tray-icon");
|
||||
|
||||
m_picture.set_halign(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_size_request(20, 20);
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <exception>
|
||||
#include <gtkmm/widget.h>
|
||||
#include <gtkmm/gestureclick.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <sigc++/functors/mem_fun.h>
|
||||
|
||||
WorkspaceIndicator::WorkspaceIndicator(HyprlandService &service, int monitorId)
|
||||
@@ -79,6 +81,23 @@ void WorkspaceIndicator::rebuild()
|
||||
auto label = Gtk::make_managed<Gtk::Label>(display);
|
||||
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->focused)
|
||||
|
||||
Reference in New Issue
Block a user