Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions include/modules/hyprland/workbar/backend.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <functional>
#include <string>

#include "modules/hyprland/backend.hpp"
#include "modules/hyprland/workbar/model.hpp"

namespace waybar::modules::hyprland::workbar {

class Backend : public EventHandler {
public:
Backend();

WorkspaceList getWorkspaces();

void onEvent(const std::string& ev) override;
void setUpdateCallback(std::function<void()> callback);

private:
IPC& ipc_;

std::function<void()> update_callback_;
};

} // namespace waybar::modules::hyprland::workbar
15 changes: 15 additions & 0 deletions include/modules/hyprland/workbar/drag_state.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <string>

namespace waybar::modules::hyprland::workbar {

struct DragState {
bool dragging = false;
std::string window_address;
int source_workspace = -1;
};

extern DragState drag_state;

} // namespace waybar::modules::hyprland::workbar
32 changes: 32 additions & 0 deletions include/modules/hyprland/workbar/model.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <string>
#include <vector>

namespace waybar::modules::hyprland::workbar {

struct WindowState {
std::string address;
std::string class_name;
std::string title;

int workspace_id;

bool active = false;
bool workspace_visible = false;
};

struct WorkspaceState {
int id;

bool active = false;
bool visible = false;

std::string monitor;

std::vector<WindowState> windows;
};

using WorkspaceList = std::vector<WorkspaceState>;

} // namespace waybar::modules::hyprland::workbar
20 changes: 20 additions & 0 deletions include/modules/hyprland/workbar/module.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "AModule.hpp"
#include "modules/hyprland/workbar/backend.hpp"
#include "modules/hyprland/workbar/widget.hpp"

namespace waybar::modules::hyprland::workbar {

class Module : public AModule {
public:
Module(const std::string& id, const Json::Value& config);

void update() override;

private:
Backend backend_;
Widget widget_;
};

} // namespace waybar::modules::hyprland::workbar
33 changes: 33 additions & 0 deletions include/modules/hyprland/workbar/widget.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <gtkmm/box.h>

#include <memory>
#include <unordered_map>
#include <vector>

#include "modules/hyprland/workbar/model.hpp"
#include "modules/hyprland/workbar/workspace_button.hpp"

namespace waybar::modules::hyprland::workbar {

class Widget : public Gtk::Box {
public:
Widget();
static Widget* instance();
WorkspaceButton* workspaceAt(int x, int y);
void setWorkspaces(const WorkspaceList& workspaces);
void beginDrag(const WindowState& window);
void updateDrag(double x, double y);
void endDrag();

private:
void clearWorkspaces();
static Widget* instance_;
std::unordered_map<int, std::unique_ptr<WorkspaceButton>> workspaces_;
bool dragging_ = false;
WindowState dragged_window_;
WorkspaceButton* hovered_workspace_ = nullptr;
};

} // namespace waybar::modules::hyprland::workbar
32 changes: 32 additions & 0 deletions include/modules/hyprland/workbar/window_icon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <gtkmm/button.h>
#include <gtkmm/image.h>

#include "modules/hyprland/workbar/model.hpp"

namespace waybar::modules::hyprland::workbar {

class WindowIcon : public Gtk::Button {
public:
explicit WindowIcon(const WindowState& window);

void setWindow(const WindowState& window);

protected:
bool on_button_press_event(GdkEventButton* event) override;
bool on_motion_notify_event(GdkEventMotion* event) override;
bool on_button_release_event(GdkEventButton* event) override;

private:
void focusWindow();
Gtk::Image image_;
WindowState window_;

bool left_pressed_ = false;
bool dragging_ = false;
double press_x_ = 0;
double press_y_ = 0;
};

} // namespace waybar::modules::hyprland::workbar
34 changes: 34 additions & 0 deletions include/modules/hyprland/workbar/workspace_button.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>

#include <memory>
#include <unordered_map>
#include <vector>

#include "modules/hyprland/workbar/model.hpp"
#include "modules/hyprland/workbar/window_icon.hpp"
#include "modules/hyprland/workbar/workspace_number.hpp"

namespace waybar::modules::hyprland::workbar {

class WorkspaceButton : public Gtk::Box {
public:
WorkspaceButton(const WorkspaceState& workspace);
int id() const;

void setWorkspace(const WorkspaceState& workspace);

private:
Gtk::Box box_;
Gtk::Box icons_;

WorkspaceNumber number_;

std::unordered_map<std::string, std::unique_ptr<WindowIcon>> window_icons_;
};

} // namespace waybar::modules::hyprland::workbar
27 changes: 27 additions & 0 deletions include/modules/hyprland/workbar/workspace_number.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <gtkmm/button.h>
#include <gtkmm/label.h>

#include "modules/hyprland/workbar/workspace_number.hpp"

namespace waybar::modules::hyprland::workbar {

class WorkspaceNumber : public Gtk::Button {
public:
explicit WorkspaceNumber(int workspace_id);
int workspaceId() const;
void setWorkspace(int workspace_id);
Glib::RefPtr<Gtk::StyleContext> style() { return get_style_context(); }

protected:
bool on_enter_notify_event(GdkEventCrossing* event) override;
bool on_leave_notify_event(GdkEventCrossing* event) override;

private:
int workspace_id_;

Gtk::Label label_;
};

} // namespace waybar::modules::hyprland::workbar
78 changes: 78 additions & 0 deletions man/waybar-hyprland-workbar.5.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
waybar-hyprland-workbar(5)

# NAME

waybar - Hyprland workbar module

# DESCRIPTION

The *workbar* module combines the functionality of the traditional *workspaces* and *taskbar* modules into a single component.

Each workspace is displayed as a single pill containing its workspace number along with icons representing the windows currently opened on that workspace.

The module communicates directly with Hyprland through Waybar's native IPC backend and does not require any external helper scripts.

The module is intended for users who prefer a workspace-centric workflow by grouping workspace navigation and window management into a single interface.

# CONFIGURATION

Addressed by *hyprland/workbar*

*rotate*: ++
typeof: integer ++
default: 0 ++
Rotates the module.

# FEATURES

- Unified replacement for Workspaces and Taskbar modules
- Displays application icons grouped by workspace
- Highlights the active workspace
- Highlights the active window
- Indicates workspaces visible on non-focused monitors
- Drag and drop windows between workspaces
- Middle-click window icons to close windows
- Native Hyprland IPC implementation
- Incremental widget updates for improved performance

# INTERACTION

Left-click workspace number::
Switch to the selected workspace.

Left-click window icon::
Switch to the corresponding workspace (if necessary) and focus the selected window.

Middle-click window icon::
Close the selected window.

Drag window icon::
Move the window to another workspace.

# EXAMPLE

```
"hyprland/workbar": {
"rotate": 0
}
```

# STYLE

The following CSS classes are available:

- *#workbar*
- *.workspace*
- *.workspace-number*
- *.workspace-number.active*
- *.workspace-number.visible*
- *.window-icon*
- *.window-icon.active*

# SEE ALSO

*waybar*(5)

*waybar-hyprland-workspaces*(5)

*waybar-hyprland-window*(5)
9 changes: 9 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,22 @@ if true
'src/modules/hyprland/windowcount.cpp',
'src/modules/hyprland/workspace.cpp',
'src/modules/hyprland/workspaces.cpp',
'src/modules/hyprland/workbar/module.cpp',
'src/modules/hyprland/workbar/widget.cpp',
'src/modules/hyprland/workbar/workspace_button.cpp',
'src/modules/hyprland/workbar/model.cpp',
'src/modules/hyprland/workbar/backend.cpp',
'src/modules/hyprland/workbar/window_icon.cpp',
'src/modules/hyprland/workbar/workspace_number.cpp',
'src/modules/hyprland/workbar/drag_state.cpp',
'src/modules/hyprland/windowcreationpayload.cpp',
)
man_files += files(
'man/waybar-hyprland-language.5.scd',
'man/waybar-hyprland-submap.5.scd',
'man/waybar-hyprland-window.5.scd',
'man/waybar-hyprland-workspaces.5.scd',
'man/waybar-hyprland-workbar.5.scd',
)
endif

Expand Down
2 changes: 0 additions & 2 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,9 @@ int waybar::Client::main(int argc, char* argv[]) {
return 1;
}
if (show_help) {
std::cout << cli << '\n';
return 0;
}
if (show_version) {
std::cout << "Waybar v" << VERSION << '\n';
return 0;
}
if (!log_level.empty()) {
Expand Down
4 changes: 4 additions & 0 deletions src/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "modules/hyprland/submap.hpp"
#include "modules/hyprland/window.hpp"
#include "modules/hyprland/windowcount.hpp"
#include "modules/hyprland/workbar/module.hpp"
#include "modules/hyprland/workspaces.hpp"
#endif
#ifdef HAVE_NIRI
Expand Down Expand Up @@ -219,6 +220,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
if (ref == "hyprland/workspaces") {
return new waybar::modules::hyprland::Workspaces(id, bar_, config_[name]);
}
if (ref == "hyprland/workbar") {
return new waybar::modules::hyprland::workbar::Module(id, config_[name]);
}
#endif
#ifdef HAVE_NIRI
if (ref == "niri/language") {
Expand Down
Loading