Skip to content

Commit

Permalink
Add niri/workspaces, niri/window, niri/language
Browse files Browse the repository at this point in the history
  • Loading branch information
YaLTeR committed Sep 2, 2024
1 parent 5d184f7 commit 5c30d42
Show file tree
Hide file tree
Showing 15 changed files with 1,131 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Sway (Workspaces, Binding mode, Focused window name)
- River (Mapping mode, Tags, Focused window name)
- Hyprland (Window Icons, Workspaces, Focused window name)
- Niri (Workspaces, Focused window name, Language)
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time
Expand Down
52 changes: 52 additions & 0 deletions include/modules/niri/backend.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include <list>
#include <mutex>
#include <string>
#include <utility>

#include "util/json.hpp"

namespace waybar::modules::niri {

class EventHandler {
public:
virtual void onEvent(const Json::Value& ev) = 0;
virtual ~EventHandler() = default;
};

class IPC {
public:
IPC() { startIPC(); }

void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler);

static Json::Value send(const Json::Value& request);

// The data members are only safe to access while dataMutex_ is locked.
std::lock_guard<std::mutex> lockData() { return std::lock_guard(dataMutex_); }
const std::vector<Json::Value> &workspaces() const { return workspaces_; }
const std::vector<Json::Value> &windows() const { return windows_; }
const std::vector<std::string> &keyboardLayoutNames() const { return keyboardLayoutNames_; }
unsigned keyboardLayoutCurrent() const { return keyboardLayoutCurrent_; }

private:
void startIPC();
static int connectToSocket();
void parseIPC(const std::string&);

std::mutex dataMutex_;
std::vector<Json::Value> workspaces_;
std::vector<Json::Value> windows_;
std::vector<std::string> keyboardLayoutNames_;
unsigned keyboardLayoutCurrent_;

util::JsonParser parser_;
std::mutex callbackMutex_;
std::list<std::pair<std::string, EventHandler*>> callbacks_;
};

inline std::unique_ptr<IPC> gIPC;

}; // namespace waybar::modules::niri
38 changes: 38 additions & 0 deletions include/modules/niri/language.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <string>

#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"

namespace waybar::modules::niri {

class Language : public ALabel, public EventHandler {
public:
Language(const std::string&, const Bar&, const Json::Value&);
~Language() override;
void update() override;

private:
void updateFromIPC();
void onEvent(const Json::Value &ev) override;
void doUpdate();

struct Layout {
std::string full_name;
std::string short_name;
std::string variant;
std::string short_description;
};

static Layout getLayout(const std::string &fullName);

std::mutex mutex_;
const Bar &bar_;

std::vector<Layout> layouts_;
unsigned current_idx_;
};

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

#include <gtkmm/button.h>
#include <json/value.h>

#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"

namespace waybar::modules::niri {

class Window : public AAppIconLabel, public EventHandler {
public:
Window(const std::string &, const Bar &, const Json::Value &);
~Window() override;
void update() override;

private:
void onEvent(const Json::Value &ev) override;
void doUpdate();
void setClass(const std::string &className, bool enable);

const Bar &bar_;

std::string oldAppId_;
};

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

#include <gtkmm/button.h>
#include <json/value.h>

#include "AModule.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"

namespace waybar::modules::niri {

class Workspaces : public AModule, public EventHandler {
public:
Workspaces(const std::string &, const Bar &, const Json::Value &);
~Workspaces() override;
void update() override;

private:
void onEvent(const Json::Value &ev) override;
void doUpdate();
Gtk::Button &addButton(const Json::Value &ws);
std::string getIcon(const std::string &value, const Json::Value &ws);

const Bar &bar_;
Gtk::Box box_;
// Map from niri workspace id to button.
std::unordered_map<uint64_t, Gtk::Button> buttons_;
};

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

# NAME

waybar - niri language module

# DESCRIPTION

The *language* module displays the currently selected language in niri.

# CONFIGURATION

Addressed by *niri/language*

*format*: ++
typeof: string ++
default: {} ++
The format, how information should be displayed.

*format-<lang>* ++
typeof: string++
Provide an alternative name to display per language where <lang> is the language of your choosing. Can be passed multiple times with multiple languages as shown by the example below.

*menu*: ++
typeof: string ++
Action that popups the menu.

*menu-file*: ++
typeof: string ++
Location of the menu descriptor file. There need to be an element of type GtkMenu with id *menu*

*menu-actions*: ++
typeof: array ++
The actions corresponding to the buttons of the menu.

# FORMAT REPLACEMENTS

*{short}*: Short name of layout (e.g. "us"). Equals to {}.

*{shortDescription}*: Short description of layout (e.g. "en").

*{long}*: Long name of layout (e.g. "English (Dvorak)").

*{variant}*: Variant of layout (e.g. "dvorak").

# EXAMPLES

```
"niri/language": {
"format": "Lang: {long}"
"format-en": "AMERICA, HELL YEAH!"
"format-tr": "As bayrakları"
}
```

# STYLE

- *#language*
81 changes: 81 additions & 0 deletions man/waybar-niri-window.5.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
waybar-niri-window(5)

# NAME

waybar - niri window module

# DESCRIPTION

The *window* module displays the title of the currently focused window in niri.

# CONFIGURATION

Addressed by *niri/window*

*format*: ++
typeof: string ++
default: {title} ++
The format, how information should be displayed. On {} the current window title is displayed.

*rewrite*: ++
typeof: object ++
Rules to rewrite window title. See *rewrite rules*.

*separate-outputs*: ++
typeof: bool ++
Show the active window of the monitor the bar belongs to, instead of the focused window.

*icon*: ++
typeof: bool ++
default: false ++
Option to hide the application icon.

*icon-size*: ++
typeof: integer ++
default: 24 ++
Option to change the size of the application icon.

# FORMAT REPLACEMENTS

See the output of "niri msg windows" for examples

*{title}*: The current title of the focused window.

*{app_id}*: The current app ID of the focused window.

# REWRITE RULES

*rewrite* is an object where keys are regular expressions and values are
rewrite rules if the expression matches. Rules may contain references to
captures of the expression.

Regular expression and replacement follow ECMA-script rules.

If no expression matches, the title is left unchanged.

Invalid expressions (e.g., mismatched parentheses) are skipped.

# EXAMPLES

```
"niri/window": {
"format": "{}",
"rewrite": {
"(.*) - Mozilla Firefox": "🌎 $1",
"(.*) - zsh": "> [$1]"
}
}
```

# STYLE

- *#window*
- *window#waybar.empty #window* When no windows are on the workspace

The following classes are applied to the entire Waybar rather than just the
window widget:

- *window#waybar.empty* When no windows are in the workspace
- *window#waybar.solo* When only one window is on the workspace
- *window#waybar.<app-id>* Where *app-id* is the app ID of the only window on
the workspace
97 changes: 97 additions & 0 deletions man/waybar-niri-workspaces.5.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
waybar-niri-workspaces(5)

# NAME

waybar - niri workspaces module

# DESCRIPTION

The *workspaces* module displays the currently used workspaces in niri.

# CONFIGURATION

Addressed by *niri/workspaces*

*all-outputs*: ++
typeof: bool ++
default: false ++
If set to false, workspaces will only be shown on the output they are on. If set to true all workspaces will be shown on every output.

*format*: ++
typeof: string ++
default: {value} ++
The format, how information should be displayed.

*format-icons*: ++
typeof: array ++
Based on the workspace name, index and state, the corresponding icon gets selected. See *icons*.

*disable-click*: ++
typeof: bool ++
default: false ++
If set to false, you can click to change workspace. If set to true this behaviour is disabled.

*disable-markup*: ++
typeof: bool ++
default: false ++
If set to true, button label will escape pango markup.

*current-only*: ++
typeof: bool ++
default: false ++
If set to true, only the active or focused workspace will be shown.

*on-update*: ++
typeof: string ++
Command to execute when the module is updated.

# FORMAT REPLACEMENTS

*{value}*: Name of the workspace, or index for unnamed workspaces,
as defined by niri.

*{name}*: Name of the workspace for named workspaces.

*{icon}*: Icon, as defined in *format-icons*.

*{index}*: Index of the workspace on its output.

*{output}*: Output where the workspace is located.

# ICONS

Additional to workspace name matching, the following *format-icons* can be set.

- *default*: Will be shown, when no string matches are found.
- *focused*: Will be shown, when workspace is focused.
- *active*: Will be shown, when workspace is active on its output.

# EXAMPLES

```
"niri/workspaces": {
"format": "{icon}",
"format-icons": {
// Named workspaces
// (you need to configure them in niri)
"browser": "",
"discord": "",
"chat": "<b></b>",
// Icons by state
"active": "",
"default": ""
}
}
```

# Style

- *#workspaces button*
- *#workspaces button.focused*: The single focused workspace.
- *#workspaces button.active*: The workspace is active (visible) on its output.
- *#workspaces button.empty*: The workspace is empty.
- *#workspaces button.current_output*: The workspace is from the same output as
the bar that it is displayed on.
- *#workspaces button#niri-workspace-<name>*: Workspaces named this, or index
for unnamed workspaces.
Loading

0 comments on commit 5c30d42

Please sign in to comment.